###############################################################################
# #
# IPFire.org - A linux based firewall #
-# Copyright (C) 2007-2021 IPFire Team <info@ipfire.org> #
+# Copyright (C) 2007-2020 IPFire Team <info@ipfire.org> #
# #
# 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 #
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
@$(PREBUILD)
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf $(DIR_DL)/$(DL_FILE)
- cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/coreutils/coreutils-8.27-uname-1.patch
- cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/coreutils/coreutils-8.32-i18n-1.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/coreutils-8.27-uname-1.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/coreutils-8.32-i18n-1.patch
# this is upstream and also fix the aarch64 build
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/coreutils/ls-restore-8.31-behavior-on-removed-directories.patch
cd $(DIR_APP) && FORCE_UNSAFE_CONFIGURE=1 && ./configure $(CONFIGURE_OPTIONS)
# Add patch for i586 to disable strong stack protector.
ifeq "$(BUILD_ARCH)" "i586"
- cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/libloc/libloc-0.9.3-perl-i586-regular-stack-protector.patch
+ cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/libloc-0.9.3-perl-i586-regular-stack-protector.patch
endif
cd $(DIR_APP) && ./autogen.sh
--- /dev/null
+diff -Naur compat-drivers-3.8.3-2-snpu.org/drivers/net/wireless/ath/regd.c compat-drivers-3.8.3-2-snpu/drivers/net/wireless/ath/regd.c
+--- compat-drivers-3.8.3-2-snpu.org/drivers/net/wireless/ath/regd.c 2013-03-15 22:55:09.000000000 +0100
++++ compat-drivers-3.8.3-2-snpu/drivers/net/wireless/ath/regd.c 2013-08-22 11:51:36.793297656 +0200
+@@ -200,6 +200,8 @@
+ u32 bandwidth = 0;
+ int r;
+
++ return;
++
+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+
+ if (!wiphy->bands[band])
+@@ -259,6 +261,8 @@
+ u32 bandwidth = 0;
+ int r;
+
++ return;
++
+ sband = wiphy->bands[IEEE80211_BAND_2GHZ];
+ if (!sband)
+ return;
+@@ -308,6 +312,8 @@
+ struct ieee80211_channel *ch;
+ unsigned int i;
+
++ return;
++
+ if (!wiphy->bands[IEEE80211_BAND_5GHZ])
+ return;
+
+@@ -514,6 +520,8 @@
+ {
+ const struct ieee80211_regdomain *regd;
+
++ return 0;
++
+ wiphy->reg_notifier = reg_notifier;
+ wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
+
--- /dev/null
+diff -up cups-1.7.5/cgi-bin/ipp-var.c.str4609 cups-1.7.5/cgi-bin/ipp-var.c
+--- cups-1.7.5/cgi-bin/ipp-var.c.str4609 2014-05-22 15:59:21.000000000 +0200
++++ cups-1.7.5/cgi-bin/ipp-var.c 2015-06-10 10:31:45.297965345 +0200
+@@ -1206,21 +1206,7 @@ cgiSetIPPObjectVars(
+ * Rewrite URIs...
+ */
+
+- if (!strcmp(name, "member_uris"))
+- {
+- char url[1024]; /* URL for class member... */
+-
+-
+- cgiRewriteURL(attr->values[i].string.text, url,
+- sizeof(url), NULL);
+-
+- snprintf(valptr, sizeof(value) - (valptr - value),
+- "<A HREF=\"%s\">%s</A>", url,
+- strrchr(attr->values[i].string.text, '/') + 1);
+- }
+- else
+- cgiRewriteURL(attr->values[i].string.text, valptr,
+- sizeof(value) - (valptr - value), NULL);
++ cgiRewriteURL(attr->values[i].string.text, valptr, sizeof(value) - (valptr - value), NULL);
+ break;
+ }
+
+diff -up cups-1.7.5/cgi-bin/template.c.str4609 cups-1.7.5/cgi-bin/template.c
+--- cups-1.7.5/cgi-bin/template.c.str4609 2014-03-05 22:11:32.000000000 +0100
++++ cups-1.7.5/cgi-bin/template.c 2015-06-10 10:31:45.297965345 +0200
+@@ -659,39 +659,7 @@ cgi_puts(const char *s, /* I - String
+ while (*s)
+ {
+ if (*s == '<')
+- {
+- /*
+- * Pass <A HREF="url"> and </A>, otherwise quote it...
+- */
+-
+- if (!_cups_strncasecmp(s, "<A HREF=\"", 9))
+- {
+- fputs("<A HREF=\"", out);
+- s += 9;
+-
+- while (*s && *s != '\"')
+- {
+- if (*s == '&')
+- fputs("&", out);
+- else
+- putc(*s, out);
+-
+- s ++;
+- }
+-
+- if (*s)
+- s ++;
+-
+- fputs("\">", out);
+- }
+- else if (!_cups_strncasecmp(s, "</A>", 4))
+- {
+- fputs("</A>", out);
+- s += 3;
+- }
+- else
+- fputs("<", out);
+- }
++ fputs("<", out);
+ else if (*s == '>')
+ fputs(">", out);
+ else if (*s == '\"')
+diff -up cups-1.7.5/scheduler/client.c.str4609 cups-1.7.5/scheduler/client.c
+--- cups-1.7.5/scheduler/client.c.str4609 2015-06-10 10:31:45.280965399 +0200
++++ cups-1.7.5/scheduler/client.c 2015-06-10 10:31:45.300965335 +0200
+@@ -598,7 +598,12 @@ cupsdCloseClient(cupsd_client_t *con) /*
+ httpClearCookie(HTTP(con));
+ httpClearFields(HTTP(con));
+
+- cupsdClearString(&con->filename);
++ if (con->filename)
++ {
++ unlink(con->filename);
++ cupsdClearString(&con->filename);
++ }
++
+ cupsdClearString(&con->command);
+ cupsdClearString(&con->options);
+ cupsdClearString(&con->query_string);
+diff -up cups-1.7.5/scheduler/env.c.str4609 cups-1.7.5/scheduler/env.c
+--- cups-1.7.5/scheduler/env.c.str4609 2015-06-10 10:31:45.208965629 +0200
++++ cups-1.7.5/scheduler/env.c 2015-06-10 10:31:45.300965335 +0200
+@@ -131,6 +131,13 @@ cupsdSetEnv(const char *name, /* I - Na
+ return;
+
+ /*
++ * Do not allow dynamic linker variables when running as root...
++ */
++
++ if (!RunUser && (!strncmp(name, "DYLD_", 5) || !strncmp(name, "LD_", 3)))
++ return;
++
++ /*
+ * See if this variable has already been defined...
+ */
+
+diff -up cups-1.7.5/scheduler/ipp.c.str4609 cups-1.7.5/scheduler/ipp.c
+--- cups-1.7.5/scheduler/ipp.c.str4609 2015-06-10 10:31:45.287965377 +0200
++++ cups-1.7.5/scheduler/ipp.c 2015-06-10 10:31:45.299965339 +0200
+@@ -412,8 +412,7 @@ cupsdProcessIPPRequest(
+ * Remote unauthenticated user masquerading as local root...
+ */
+
+- _cupsStrFree(username->values[0].string.text);
+- username->values[0].string.text = _cupsStrAlloc(RemoteRoot);
++ ippSetString(con->request, &username, 0, RemoteRoot);
+ }
+ }
+
+@@ -1576,7 +1575,7 @@ add_job(cupsd_client_t *con, /* I - Cl
+ cupsdSetString(&job->username, con->username);
+
+ if (attr)
+- cupsdSetString(&attr->values[0].string.text, con->username);
++ ippSetString(job->attrs, &attr, 0, con->username);
+ }
+ else if (attr)
+ {
+@@ -1594,9 +1593,8 @@ add_job(cupsd_client_t *con, /* I - Cl
+ "job-originating-user-name", NULL, job->username);
+ else
+ {
+- attr->group_tag = IPP_TAG_JOB;
+- _cupsStrFree(attr->name);
+- attr->name = _cupsStrAlloc("job-originating-user-name");
++ ippSetGroupTag(job->attrs, &attr, IPP_TAG_JOB);
++ ippSetName(job->attrs, &attr, "job-originating-user-name");
+ }
+
+ if (con->username[0] || auth_info)
+@@ -1630,48 +1628,11 @@ add_job(cupsd_client_t *con, /* I - Cl
+ * Also, we can only have 1 value and it must be a name value.
+ */
+
+- switch (attr->value_tag)
+- {
+- case IPP_TAG_STRING :
+- case IPP_TAG_TEXTLANG :
+- case IPP_TAG_NAMELANG :
+- case IPP_TAG_TEXT :
+- case IPP_TAG_NAME :
+- case IPP_TAG_KEYWORD :
+- case IPP_TAG_URI :
+- case IPP_TAG_URISCHEME :
+- case IPP_TAG_CHARSET :
+- case IPP_TAG_LANGUAGE :
+- case IPP_TAG_MIMETYPE :
+- /*
+- * Free old strings...
+- */
+-
+- for (i = 0; i < attr->num_values; i ++)
+- {
+- _cupsStrFree(attr->values[i].string.text);
+- attr->values[i].string.text = NULL;
+- if (attr->values[i].string.language)
+- {
+- _cupsStrFree(attr->values[i].string.language);
+- attr->values[i].string.language = NULL;
+- }
+- }
+-
+- default :
+- break;
+- }
+-
+- /*
+- * Use the default connection hostname instead...
+- */
+-
+- attr->value_tag = IPP_TAG_NAME;
+- attr->num_values = 1;
+- attr->values[0].string.text = _cupsStrAlloc(con->http.hostname);
++ ippDeleteAttribute(job->attrs, attr);
++ ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, "job-originating-host-name", NULL, con->http.hostname);
+ }
+-
+- attr->group_tag = IPP_TAG_JOB;
++ else
++ ippSetGroupTag(job->attrs, &attr, IPP_TAG_JOB);
+ }
+ else
+ {
+@@ -1767,8 +1728,8 @@ add_job(cupsd_client_t *con, /* I - Cl
+
+ attr = ippAddStrings(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, "job-sheets",
+ 2, NULL, NULL);
+- attr->values[0].string.text = _cupsStrRetain(printer->job_sheets[0]);
+- attr->values[1].string.text = _cupsStrRetain(printer->job_sheets[1]);
++ ippSetString(job->attrs, &attr, 0, printer->job_sheets[0]);
++ ippSetString(job->attrs, &attr, 1, printer->job_sheets[1]);
+ }
+
+ job->job_sheets = attr;
+@@ -1794,7 +1755,7 @@ add_job(cupsd_client_t *con, /* I - Cl
+ * Force the leading banner to have the classification on it...
+ */
+
+- cupsdSetString(&attr->values[0].string.text, Classification);
++ ippSetString(job->attrs, &attr, 0, Classification);
+
+ cupsdLogJob(job, CUPSD_LOG_NOTICE, "CLASSIFICATION FORCED "
+ "job-sheets=\"%s,none\", "
+@@ -1811,7 +1772,7 @@ add_job(cupsd_client_t *con, /* I - Cl
+ * Can't put two different security markings on the same document!
+ */
+
+- cupsdSetString(&attr->values[1].string.text, attr->values[0].string.text);
++ ippSetString(job->attrs, &attr, 1, attr->values[0].string.text);
+
+ cupsdLogJob(job, CUPSD_LOG_NOTICE, "CLASSIFICATION FORCED "
+ "job-sheets=\"%s,%s\", "
+@@ -1851,18 +1812,18 @@ add_job(cupsd_client_t *con, /* I - Cl
+ if (attr->num_values > 1 &&
+ !strcmp(attr->values[0].string.text, attr->values[1].string.text))
+ {
+- cupsdSetString(&(attr->values[0].string.text), Classification);
+- cupsdSetString(&(attr->values[1].string.text), Classification);
++ ippSetString(job->attrs, &attr, 0, Classification);
++ ippSetString(job->attrs, &attr, 1, Classification);
+ }
+ else
+ {
+ if (attr->num_values == 1 ||
+ strcmp(attr->values[0].string.text, "none"))
+- cupsdSetString(&(attr->values[0].string.text), Classification);
++ ippSetString(job->attrs, &attr, 0, Classification);
+
+ if (attr->num_values > 1 &&
+ strcmp(attr->values[1].string.text, "none"))
+- cupsdSetString(&(attr->values[1].string.text), Classification);
++ ippSetString(job->attrs, &attr, 1, Classification);
+ }
+
+ if (attr->num_values > 1)
+@@ -3098,8 +3059,8 @@ authenticate_job(cupsd_client_t *con, /
+
+ if (attr)
+ {
+- attr->value_tag = IPP_TAG_KEYWORD;
+- cupsdSetString(&(attr->values[0].string.text), "no-hold");
++ ippSetValueTag(job->attrs, &attr, IPP_TAG_KEYWORD);
++ ippSetString(job->attrs, &attr, 0, "no-hold");
+ }
+
+ /*
+@@ -8224,11 +8185,7 @@ print_job(cupsd_client_t *con, /* I -
+ filetype->type);
+
+ if (format)
+- {
+- _cupsStrFree(format->values[0].string.text);
+-
+- format->values[0].string.text = _cupsStrAlloc(mimetype);
+- }
++ ippSetString(con->request, &format, 0, mimetype);
+ else
+ ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_MIMETYPE,
+ "document-format", NULL, mimetype);
+@@ -8765,10 +8722,8 @@ release_job(cupsd_client_t *con, /* I -
+
+ if (attr)
+ {
+- _cupsStrFree(attr->values[0].string.text);
+-
+- attr->value_tag = IPP_TAG_KEYWORD;
+- attr->values[0].string.text = _cupsStrAlloc("no-hold");
++ ippSetValueTag(job->attrs, &attr, IPP_TAG_KEYWORD);
++ ippSetString(job->attrs, &attr, 0, "no-hold");
+
+ cupsdAddEvent(CUPSD_EVENT_JOB_CONFIG_CHANGED, cupsdFindDest(job->dest), job,
+ "Job job-hold-until value changed by user.");
+@@ -9461,11 +9416,7 @@ send_document(cupsd_client_t *con, /* I
+
+ if ((jformat = ippFindAttribute(job->attrs, "document-format",
+ IPP_TAG_MIMETYPE)) != NULL)
+- {
+- _cupsStrFree(jformat->values[0].string.text);
+-
+- jformat->values[0].string.text = _cupsStrAlloc(mimetype);
+- }
++ ippSetString(job->attrs, &jformat, 0, mimetype);
+ else
+ ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_MIMETYPE,
+ "document-format", NULL, mimetype);
+diff -up cups-1.7.5/scheduler/job.c.str4609 cups-1.7.5/scheduler/job.c
+--- cups-1.7.5/scheduler/job.c.str4609 2015-06-10 10:31:45.288965374 +0200
++++ cups-1.7.5/scheduler/job.c 2015-06-10 10:31:45.299965339 +0200
+@@ -375,7 +375,7 @@ cupsdCheckJobs(void)
+
+ if ((attr = ippFindAttribute(job->attrs, "job-actual-printer-uri",
+ IPP_TAG_URI)) != NULL)
+- cupsdSetString(&attr->values[0].string.text, printer->uri);
++ ippSetString(job->attrs, &attr, 0, printer->uri);
+ else
+ ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI,
+ "job-actual-printer-uri", NULL, printer->uri);
+@@ -2109,7 +2109,7 @@ cupsdMoveJob(cupsd_job_t *job, /* I
+
+ if ((attr = ippFindAttribute(job->attrs, "job-printer-uri",
+ IPP_TAG_URI)) != NULL)
+- cupsdSetString(&(attr->values[0].string.text), p->uri);
++ ippSetString(job->attrs, &attr, 0, p->uri);
+
+ cupsdAddEvent(CUPSD_EVENT_JOB_STOPPED, p, job,
+ "Job #%d moved from %s to %s.", job->id, olddest,
+@@ -2306,7 +2306,7 @@ cupsdSetJobHoldUntil(cupsd_job_t *job, /
+ attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME);
+
+ if (attr)
+- cupsdSetString(&(attr->values[0].string.text), when);
++ ippSetString(job->attrs, &attr, 0, when);
+ else
+ attr = ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_KEYWORD,
+ "job-hold-until", NULL, when);
+@@ -2560,8 +2560,8 @@ cupsdSetJobState(
+
+ if (attr)
+ {
+- attr->value_tag = IPP_TAG_KEYWORD;
+- cupsdSetString(&(attr->values[0].string.text), "no-hold");
++ ippSetValueTag(job->attrs, &attr, IPP_TAG_KEYWORD);
++ ippSetString(job->attrs, &attr, 0, "no-hold");
+ }
+
+ default :
+@@ -4598,7 +4598,7 @@ start_job(cupsd_job_t *job, /* I -
+ "job-printer-state-message",
+ IPP_TAG_TEXT);
+ if (job->printer_message)
+- cupsdSetString(&(job->printer_message->values[0].string.text), "");
++ ippSetString(job->attrs, &job->printer_message, 0, "");
+
+ ippSetString(job->attrs, &job->reasons, 0, "job-printing");
+ cupsdSetJobState(job, IPP_JOB_PROCESSING, CUPSD_JOB_DEFAULT, NULL);
+@@ -5216,15 +5216,14 @@ update_job_attrs(cupsd_job_t *job, /* I
+ if (job->state_value != IPP_JOB_PROCESSING &&
+ job->status_level == CUPSD_LOG_INFO)
+ {
+- cupsdSetString(&(job->printer_message->values[0].string.text), "");
++ ippSetString(job->attrs, &job->printer_message, 0, "");
+
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
+ }
+ else if (job->printer->state_message[0] && do_message)
+ {
+- cupsdSetString(&(job->printer_message->values[0].string.text),
+- job->printer->state_message);
++ ippSetString(job->attrs, &job->printer_message, 0, job->printer->state_message);
+
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
+diff -up cups-1.7.5/scheduler/main.c.str4609 cups-1.7.5/scheduler/main.c
+--- cups-1.7.5/scheduler/main.c.str4609 2015-06-10 10:31:45.265965447 +0200
++++ cups-1.7.5/scheduler/main.c 2015-06-10 10:31:45.300965335 +0200
+@@ -1205,8 +1205,8 @@ cupsdAddString(cups_array_t **a, /* IO -
+ if (!*a)
+ *a = cupsArrayNew3((cups_array_func_t)strcmp, NULL,
+ (cups_ahash_func_t)NULL, 0,
+- (cups_acopy_func_t)_cupsStrAlloc,
+- (cups_afree_func_t)_cupsStrFree);
++ (cups_acopy_func_t)strdup,
++ (cups_afree_func_t)free);
+
+ return (cupsArrayAdd(*a, (char *)s));
+ }
+@@ -1236,7 +1236,7 @@ cupsdClearString(char **s) /* O - Strin
+ {
+ if (s && *s)
+ {
+- _cupsStrFree(*s);
++ free(*s);
+ *s = NULL;
+ }
+ }
+@@ -1317,10 +1317,10 @@ cupsdSetString(char **s, /* O - N
+ return;
+
+ if (*s)
+- _cupsStrFree(*s);
++ free(*s);
+
+ if (v)
+- *s = _cupsStrAlloc(v);
++ *s = strdup(v);
+ else
+ *s = NULL;
+ }
+@@ -1351,13 +1351,13 @@ cupsdSetStringf(char **s, /* O -
+ vsnprintf(v, sizeof(v), f, ap);
+ va_end(ap);
+
+- *s = _cupsStrAlloc(v);
++ *s = strdup(v);
+ }
+ else
+ *s = NULL;
+
+ if (olds)
+- _cupsStrFree(olds);
++ free(olds);
+ }
+
+
+@@ -1804,8 +1804,7 @@ process_children(void)
+ }
+
+ if (job->printer_message)
+- cupsdSetString(&(job->printer_message->values[0].string.text),
+- message);
++ ippSetString(job->attrs, &job->printer_message, 0, message);
+ }
+ }
+
--- /dev/null
+Submitted By: Dan Nicholson <dnicholson AT linuxfromscratch DOT org>
+Date: 2006-09-02
+Initial Package Version: 4.4.20
+Origin: Upstream - http://www.sleepycat.com/update/4.4.20/patch.4.4.20.html
+Description: Bug fixes provided by the developer. Contains patches 1-4.
+
+diff -pNur db-4.4.20.orig/db/db_cam.c db-4.4.20/db/db_cam.c
+--- db-4.4.20.orig/db/db_cam.c 2006-01-10 16:19:21.000000000 +0000
++++ db-4.4.20/db/db_cam.c 2006-08-03 14:31:20.220319610 +0000
+@@ -579,11 +579,12 @@ __db_c_get(dbc_arg, key, data, flags)
+ flags == DB_NEXT || flags == DB_NEXT_DUP || flags == DB_PREV)) {
+ if (tmp_rmw && (ret = dbc_arg->c_am_writelock(dbc_arg)) != 0)
+ return (ret);
+- if ((ret = __db_c_idup(cp->opd, &opd, DB_POSITION)) != 0)
++ if (F_ISSET(dbc_arg, DBC_TRANSIENT))
++ opd = cp->opd;
++ else if ((ret = __db_c_idup(cp->opd, &opd, DB_POSITION)) != 0)
+ return (ret);
+
+- switch (ret =
+- opd->c_am_get(opd, key, data, flags, NULL)) {
++ switch (ret = opd->c_am_get(opd, key, data, flags, NULL)) {
+ case 0:
+ goto done;
+ case DB_NOTFOUND:
+@@ -596,12 +597,18 @@ __db_c_get(dbc_arg, key, data, flags)
+ if ((ret = __db_c_close(opd)) != 0)
+ goto err;
+ opd = NULL;
++ if (F_ISSET(dbc_arg, DBC_TRANSIENT))
++ cp->opd = NULL;
+ break;
+ }
+ goto err;
+ default:
+ goto err;
+ }
++ } else if (cp->opd != NULL && F_ISSET(dbc_arg, DBC_TRANSIENT)) {
++ if ((ret = __db_c_close(cp->opd)) != 0)
++ goto err;
++ cp->opd = NULL;
+ }
+
+ /*
+diff -pNur db-4.4.20.orig/mp/mp_fget.c db-4.4.20/mp/mp_fget.c
+--- db-4.4.20.orig/mp/mp_fget.c 2005-10-12 17:53:36.000000000 +0000
++++ db-4.4.20/mp/mp_fget.c 2006-08-03 14:31:20.223318410 +0000
+@@ -587,8 +587,11 @@ alloc: /*
+ */
+ if (state != SECOND_MISS && bhp->ref == 1) {
+ bhp->priority = UINT32_MAX;
+- SH_TAILQ_REMOVE(&hp->hash_bucket, bhp, hq, __bh);
+- SH_TAILQ_INSERT_TAIL(&hp->hash_bucket, bhp, hq);
++ if (SH_TAILQ_FIRST(&hp->hash_bucket, __bh) !=
++ SH_TAILQ_LAST(&hp->hash_bucket, hq, __bh)) {
++ SH_TAILQ_REMOVE(&hp->hash_bucket, bhp, hq, __bh);
++ SH_TAILQ_INSERT_TAIL(&hp->hash_bucket, bhp, hq);
++ }
+ hp->hash_priority =
+ SH_TAILQ_FIRSTP(&hp->hash_bucket, __bh)->priority;
+ }
+diff -pNur db-4.4.20.orig/qam/qam_files.c db-4.4.20/qam/qam_files.c
+--- db-4.4.20.orig/qam/qam_files.c 2005-10-20 18:57:12.000000000 +0000
++++ db-4.4.20/qam/qam_files.c 2006-08-03 14:31:20.211323209 +0000
+@@ -411,6 +411,12 @@ __qam_fremove(dbp, pgnoaddr)
+ DB_APP_DATA, buf, 0, NULL, &real_name)) != 0)
+ goto err;
+ #endif
++
++ mpf = array->mpfarray[offset].mpf;
++ /* This extent my already be marked for delete and closed. */
++ if (mpf == NULL)
++ goto err;
++
+ /*
+ * The log must be flushed before the file is deleted. We depend on
+ * the log record of the last delete to recreate the file if we crash.
+@@ -418,7 +424,6 @@ __qam_fremove(dbp, pgnoaddr)
+ if (LOGGING_ON(dbenv) && (ret = __log_flush(dbenv, NULL)) != 0)
+ goto err;
+
+- mpf = array->mpfarray[offset].mpf;
+ (void)__memp_set_flags(mpf, DB_MPOOL_UNLINK, 1);
+ /* Someone could be real slow, let them close it down. */
+ if (array->mpfarray[offset].pinref != 0)
+diff -pNur db-4.4.20.orig/txn/txn.c db-4.4.20/txn/txn.c
+--- db-4.4.20.orig/txn/txn.c 2005-11-01 14:50:03.000000000 +0000
++++ db-4.4.20/txn/txn.c 2006-08-03 14:31:20.215321609 +0000
+@@ -1049,12 +1049,14 @@ __txn_set_name(txn, name)
+ return (ret);
+ memcpy(txn->name, name, len);
+
++ TXN_SYSTEM_LOCK(dbenv);
+ if (td->name != INVALID_ROFF) {
+ __db_shalloc_free(
+ &mgr->reginfo, R_ADDR(&mgr->reginfo, td->name));
+ td->name = INVALID_ROFF;
+ }
+ if ((ret = __db_shalloc(&mgr->reginfo, len, 0, &p)) != 0) {
++ TXN_SYSTEM_UNLOCK(dbenv);
+ __db_err(dbenv,
+ "Unable to allocate memory for transaction name");
+
+@@ -1063,6 +1065,7 @@ __txn_set_name(txn, name)
+
+ return (ret);
+ }
++ TXN_SYSTEM_UNLOCK(dbenv);
+ td->name = R_OFFSET(&mgr->reginfo, p);
+ memcpy(p, name, len);
+
--- /dev/null
+diff -Naur iptables-1.4.6.org/extensions/.ipp2p-test iptables-1.4.6/extensions/.ipp2p-test
+--- iptables-1.4.6.org/extensions/.ipp2p-test 1970-01-01 01:00:00.000000000 +0100
++++ iptables-1.4.6/extensions/.ipp2p-test 2010-02-13 20:02:52.000000000 +0100
+@@ -0,0 +1,2 @@
++#! /bin/sh
++[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_ipp2p.h ] && echo ipp2p
+diff -Naur iptables-1.4.6.org/extensions/libipt_ipp2p.c iptables-1.4.6/extensions/libipt_ipp2p.c
+--- iptables-1.4.6.org/extensions/libipt_ipp2p.c 1970-01-01 01:00:00.000000000 +0100
++++ iptables-1.4.6/extensions/libipt_ipp2p.c 2010-02-13 20:02:52.000000000 +0100
+@@ -0,0 +1,424 @@
++#include <stdio.h>
++#include <netdb.h>
++#include <string.h>
++#include <stdlib.h>
++#include <getopt.h>
++#include <ctype.h>
++
++#include <iptables.h>
++
++#include <linux/netfilter_ipv4/ipt_ipp2p.h>
++
++#ifndef XTABLES_VERSION
++#define XTABLES_VERSION IPTABLES_VERSION
++#endif
++
++#ifdef IPT_LIB_DIR
++#define xtables_target iptables_target
++#define xtables_register_target register_target
++#endif
++
++static void
++help(void)
++{
++ printf(
++ "IPP2P v%s options:\n"
++ " --ipp2p Grab all known p2p packets\n"
++ " --edk [TCP&UDP] All known eDonkey/eMule/Overnet packets\n"
++ " --dc [TCP] All known Direct Connect packets\n"
++ " --kazaa [TCP&UDP] All known KaZaA packets\n"
++ " --gnu [TCP&UDP] All known Gnutella packets\n"
++ " --bit [TCP&UDP] All known BitTorrent packets\n"
++ " --apple [TCP] All known AppleJuice packets\n"
++ " --winmx [TCP] All known WinMX\n"
++ " --soul [TCP] All known SoulSeek\n"
++ " --ares [TCP] All known Ares\n\n"
++ " EXPERIMENTAL protocols (please send feedback to: ipp2p@ipp2p.org) :\n"
++ " --mute [TCP] All known Mute packets\n"
++ " --waste [TCP] All known Waste packets\n"
++ " --xdcc [TCP] All known XDCC packets (only xdcc login)\n\n"
++ " DEBUG SUPPPORT, use only if you know why\n"
++ " --debug Generate kernel debug output, THIS WILL SLOW DOWN THE FILTER\n"
++ "\nNote that the follwing options will have the same meaning:\n"
++ " '--ipp2p' is equal to '--edk --dc --kazaa --gnu --bit --apple --winmx --soul --ares'\n"
++ "\nIPP2P was intended for TCP only. Due to increasing usage of UDP we needed to change this.\n"
++ "You can now use -p udp to search UDP packets only or without -p switch to search UDP and TCP packets.\n"
++ "\nSee README included with this package for more details or visit http://www.ipp2p.org\n"
++ "\nExamples:\n"
++ " iptables -A FORWARD -m ipp2p --ipp2p -j MARK --set-mark 0x01\n"
++ " iptables -A FORWARD -p udp -m ipp2p --kazaa --bit -j DROP\n"
++ " iptables -A FORWARD -p tcp -m ipp2p --edk --soul -j DROP\n\n"
++ , IPP2P_VERSION);
++}
++
++static struct option opts[] = {
++ { "ipp2p", 0, 0, '1' },
++ { "edk", 0, 0, '2' },
++ { "dc", 0, 0, '7' },
++ { "gnu", 0, 0, '9' },
++ { "kazaa", 0, 0, 'a' },
++ { "bit", 0, 0, 'b' },
++ { "apple", 0, 0, 'c' },
++ { "soul", 0, 0, 'd' },
++ { "winmx", 0, 0, 'e' },
++ { "ares", 0, 0, 'f' },
++ { "mute", 0, 0, 'g' },
++ { "waste", 0, 0, 'h' },
++ { "xdcc", 0, 0, 'i' },
++ { "debug", 0, 0, 'j' },
++ {0}
++};
++
++
++static void
++#ifdef _XTABLES_H
++init(struct xt_entry_match *m)
++#else
++init(struct ipt_entry_match *t, unsigned int *nfcache)
++#endif
++{
++ struct ipt_p2p_info *info = (struct ipt_p2p_info *)m->data;
++
++#ifndef _XTABLES_H
++ *nfcache |= NFC_UNKNOWN;
++#endif
++
++ /*init the module with default values*/
++ info->cmd = 0;
++ info->debug = 0;
++
++}
++
++
++static int
++parse(int c, char **argv, int invert, unsigned int *flags,
++#ifdef _XTABLES_H
++ const void *entry, struct xt_entry_match **match)
++#else
++ const struct ipt_entry *entry, unsigned int *nfcache, struct ipt_entry_match **match)
++#endif
++{
++ struct ipt_p2p_info *info = (struct ipt_p2p_info *)(*match)->data;
++
++ switch (c) {
++ case '1': /*cmd: ipp2p*/
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified once!");
++
++/* if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p-data' may only be "
++ "specified alone!");
++*/
++
++ if ((*flags) != 0)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if (invert) xtables_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += SHORT_HAND_IPP2P;
++ info->cmd = *flags;
++ break;
++
++ case '2': /*cmd: edk*/
++ if ((*flags & IPP2P_EDK) == IPP2P_EDK)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--edk' may only be "
++ "specified once");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++/* if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p-data' may only be "
++ "specified alone!");*/
++ if ((*flags & IPP2P_DATA_EDK) == IPP2P_DATA_EDK)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: use `--edk' OR `--edk-data' but not both of them!");
++ if (invert) xtables_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_EDK;
++ info->cmd = *flags;
++ break;
++
++
++ case '7': /*cmd: dc*/
++ if ((*flags & IPP2P_DC) == IPP2P_DC)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--dc' may only be "
++ "specified once!");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++/* if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p-data' may only be "
++ "specified alone!");*/
++ if ((*flags & IPP2P_DATA_DC) == IPP2P_DATA_DC)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: use `--dc' OR `--dc-data' but not both of them!");
++ if (invert) xtables_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_DC;
++ info->cmd = *flags;
++ break;
++
++
++ case '9': /*cmd: gnu*/
++ if ((*flags & IPP2P_GNU) == IPP2P_GNU)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--gnu' may only be "
++ "specified once!");
++/* if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p-data' may only be "
++ "specified alone!");*/
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if ((*flags & IPP2P_DATA_GNU) == IPP2P_DATA_GNU)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: use `--gnu' OR `--gnu-data' but not both of them!");
++ if (invert) xtables_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_GNU;
++ info->cmd = *flags;
++ break;
++
++ case 'a': /*cmd: kazaa*/
++ if ((*flags & IPP2P_KAZAA) == IPP2P_KAZAA)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--kazaa' may only be "
++ "specified once!");
++/* if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p-data' may only be "
++ "specified alone!");*/
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if ((*flags & IPP2P_DATA_KAZAA) == IPP2P_DATA_KAZAA)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: use `--kazaa' OR `--kazaa-data' but not both of them!");
++ if (invert) xtables_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_KAZAA;
++ info->cmd = *flags;
++ break;
++
++ case 'b': /*cmd: bit*/
++ if ((*flags & IPP2P_BIT) == IPP2P_BIT)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--bit' may only be "
++ "specified once!");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if (invert) xtables_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_BIT;
++ info->cmd = *flags;
++ break;
++
++ case 'c': /*cmd: apple*/
++ if ((*flags & IPP2P_APPLE) == IPP2P_APPLE)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--apple' may only be "
++ "specified once!");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if (invert) xtables_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_APPLE;
++ info->cmd = *flags;
++ break;
++
++
++ case 'd': /*cmd: soul*/
++ if ((*flags & IPP2P_SOUL) == IPP2P_SOUL)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--soul' may only be "
++ "specified once!");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if (invert) xtables_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_SOUL;
++ info->cmd = *flags;
++ break;
++
++
++ case 'e': /*cmd: winmx*/
++ if ((*flags & IPP2P_WINMX) == IPP2P_WINMX)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--winmx' may only be "
++ "specified once!");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if (invert) xtables_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_WINMX;
++ info->cmd = *flags;
++ break;
++
++ case 'f': /*cmd: ares*/
++ if ((*flags & IPP2P_ARES) == IPP2P_ARES)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ares' may only be "
++ "specified once!");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if (invert) xtables_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_ARES;
++ info->cmd = *flags;
++ break;
++
++ case 'g': /*cmd: mute*/
++ if ((*flags & IPP2P_MUTE) == IPP2P_MUTE)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--mute' may only be "
++ "specified once!");
++ if (invert) xtables_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_MUTE;
++ info->cmd = *flags;
++ break;
++ case 'h': /*cmd: waste*/
++ if ((*flags & IPP2P_WASTE) == IPP2P_WASTE)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--waste' may only be "
++ "specified once!");
++ if (invert) xtables_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_WASTE;
++ info->cmd = *flags;
++ break;
++ case 'i': /*cmd: xdcc*/
++ if ((*flags & IPP2P_XDCC) == IPP2P_XDCC)
++ xtables_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ares' may only be "
++ "specified once!");
++ if (invert) xtables_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_XDCC;
++ info->cmd = *flags;
++ break;
++
++ case 'j': /*cmd: debug*/
++ if (invert) xtables_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ info->debug = 1;
++ break;
++
++ default:
++// xtables_error(PARAMETER_PROBLEM,
++// "\nipp2p-parameter problem: for ipp2p usage type: iptables -m ipp2p --help\n");
++ return 0;
++ }
++ return 1;
++}
++
++
++static void
++final_check(unsigned int flags)
++{
++ if (!flags)
++ xtables_error(PARAMETER_PROBLEM,
++ "\nipp2p-parameter problem: for ipp2p usage type: iptables -m ipp2p --help\n");
++}
++
++static void
++#ifdef _XTABLES_H
++print(const void *ip,
++ const struct xt_entry_match *match,
++#else
++print(const struct ipt_ip *ip,
++ const struct ipt_entry_match *match,
++#endif
++ int numeric)
++{
++ struct ipt_p2p_info *info = (struct ipt_p2p_info *)match->data;
++
++ printf("ipp2p v%s", IPP2P_VERSION);
++ if ((info->cmd & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P) printf(" --ipp2p");
++// if ((info->cmd & SHORT_HAND_DATA) == SHORT_HAND_DATA) printf(" --ipp2p-data");
++ if ((info->cmd & IPP2P_KAZAA) == IPP2P_KAZAA) printf(" --kazaa");
++// if ((info->cmd & IPP2P_DATA_KAZAA) == IPP2P_DATA_KAZAA) printf(" --kazaa-data");
++// if ((info->cmd & IPP2P_DATA_GNU) == IPP2P_DATA_GNU) printf(" --gnu-data");
++ if ((info->cmd & IPP2P_GNU) == IPP2P_GNU) printf(" --gnu");
++ if ((info->cmd & IPP2P_EDK) == IPP2P_EDK) printf(" --edk");
++// if ((info->cmd & IPP2P_DATA_EDK) == IPP2P_DATA_EDK) printf(" --edk-data");
++// if ((info->cmd & IPP2P_DATA_DC) == IPP2P_DATA_DC) printf(" --dc-data");
++ if ((info->cmd & IPP2P_DC) == IPP2P_DC) printf(" --dc");
++ if ((info->cmd & IPP2P_BIT) == IPP2P_BIT) printf(" --bit");
++ if ((info->cmd & IPP2P_APPLE) == IPP2P_APPLE) printf(" --apple");
++ if ((info->cmd & IPP2P_SOUL) == IPP2P_SOUL) printf(" --soul");
++ if ((info->cmd & IPP2P_WINMX) == IPP2P_WINMX) printf(" --winmx");
++ if ((info->cmd & IPP2P_ARES) == IPP2P_ARES) printf(" --ares");
++ if ((info->cmd & IPP2P_MUTE) == IPP2P_MUTE) printf(" --mute");
++ if ((info->cmd & IPP2P_WASTE) == IPP2P_WASTE) printf(" --waste");
++ if ((info->cmd & IPP2P_XDCC) == IPP2P_XDCC) printf(" --xdcc");
++ if (info->debug != 0) printf(" --debug");
++ printf(" ");
++}
++
++static void
++#ifdef _XTABLES_H
++save(const void *ip,
++ const struct xt_entry_match *match)
++#else
++save(const struct ipt_ip *ip,
++ const struct ipt_entry_match *match)
++#endif
++{
++ struct ipt_p2p_info *info = (struct ipt_p2p_info *)match->data;
++
++ if ((info->cmd & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P) printf("--ipp2p ");
++// if ((info->cmd & SHORT_HAND_DATA) == SHORT_HAND_DATA) printf("--ipp2p-data ");
++ if ((info->cmd & IPP2P_KAZAA) == IPP2P_KAZAA) printf("--kazaa ");
++// if ((info->cmd & IPP2P_DATA_KAZAA) == IPP2P_DATA_KAZAA) printf("--kazaa-data ");
++// if ((info->cmd & IPP2P_DATA_GNU) == IPP2P_DATA_GNU) printf("--gnu-data ");
++ if ((info->cmd & IPP2P_GNU) == IPP2P_GNU) printf("--gnu ");
++ if ((info->cmd & IPP2P_EDK) == IPP2P_EDK) printf("--edk ");
++// if ((info->cmd & IPP2P_DATA_EDK) == IPP2P_DATA_EDK) printf("--edk-data ");
++// if ((info->cmd & IPP2P_DATA_DC) == IPP2P_DATA_DC) printf("--dc-data ");
++ if ((info->cmd & IPP2P_DC) == IPP2P_DC) printf("--dc ");
++ if ((info->cmd & IPP2P_BIT) == IPP2P_BIT) printf("--bit ");
++ if ((info->cmd & IPP2P_APPLE) == IPP2P_APPLE) printf("--apple ");
++ if ((info->cmd & IPP2P_SOUL) == IPP2P_SOUL) printf("--soul ");
++ if ((info->cmd & IPP2P_WINMX) == IPP2P_WINMX) printf("--winmx ");
++ if ((info->cmd & IPP2P_ARES) == IPP2P_ARES) printf("--ares ");
++ if ((info->cmd & IPP2P_MUTE) == IPP2P_MUTE) printf(" --mute");
++ if ((info->cmd & IPP2P_WASTE) == IPP2P_WASTE) printf(" --waste");
++ if ((info->cmd & IPP2P_XDCC) == IPP2P_XDCC) printf(" --xdcc");
++ if (info->debug != 0) printf("--debug ");
++}
++
++
++static
++struct xtables_match ipp2p=
++{
++ .next = NULL,
++ .name = "ipp2p",
++ .version = XTABLES_VERSION,
++ .size = XT_ALIGN(sizeof(struct ipt_p2p_info)),
++ .userspacesize = XT_ALIGN(sizeof(struct ipt_p2p_info)),
++ .help = &help,
++ .init = &init,
++ .parse = &parse,
++ .final_check = &final_check,
++ .print = &print,
++ .save = &save,
++ .extra_opts = opts
++};
++
++
++
++void _init(void)
++{
++ xtables_register_match(&ipp2p);
++}
++
+diff -Naur iptables-1.4.6.org/extensions/libipt_ipp2p.man iptables-1.4.6/extensions/libipt_ipp2p.man
+--- iptables-1.4.6.org/extensions/libipt_ipp2p.man 1970-01-01 01:00:00.000000000 +0100
++++ iptables-1.4.6/extensions/libipt_ipp2p.man 2010-02-13 20:02:52.000000000 +0100
+@@ -0,0 +1,43 @@
++This module matches certain packets in P2P flows. It is not
++designed to match all packets belonging to a P2P connection -
++use IPP2P together with CONNMARK for this purpose. Also visit
++http://www.ipp2p.org for detailed information.
++
++Use it together with -p tcp or -p udp to search these protocols
++only or without -p switch to search packets of both protocols.
++
++IPP2P provides the following options:
++.TP
++.B "--edk "
++Matches as many eDonkey/eMule packets as possible.
++.TP
++.B "--kazaa "
++Matches as many KaZaA packets as possible.
++.TP
++.B "--gnu "
++Matches as many Gnutella packets as possible.
++.TP
++.B "--dc "
++Matches as many Direct Connect packets as possible.
++.TP
++.B "--bit "
++Matches BitTorrent packets.
++.TP
++.B "--apple "
++Matches AppleJuice packets.
++.TP
++.B "--soul "
++Matches some SoulSeek packets. Considered as beta, use careful!
++.TP
++.B "--winmx "
++Matches some WinMX packets. Considered as beta, use careful!
++.TP
++.B "--ares "
++Matches Ares and AresLite packets. Use together with -j DROP only.
++.TP
++.B "--ipp2p "
++Short hand for: --edk --kazaa --gnu --dc
++.TP
++.B "--debug "
++Prints some information about each hit into kernel logfile. May
++produce huge logfiles so beware!
--- /dev/null
+diff -urN iputils/clockdiff.c iputils.new/clockdiff.c
+--- iputils/clockdiff.c 2002-02-22 19:10:59.000000000 -0500
++++ iputils.new/clockdiff.c 2003-09-10 09:20:28.000000000 -0400
+@@ -2,6 +2,7 @@
+ #include <sys/types.h>
+ #include <sys/param.h>
+ #include <stdio.h>
++#include <linux/types.h>
+ #include <unistd.h>
+ #include <stdlib.h>
+ #include <math.h>
+diff -urN iputils/ping6.c iputils.new/ping6.c
+--- iputils/ping6.c 2003-09-10 17:27:48.000000000 -0400
++++ iputils.new/ping6.c 2003-09-10 17:22:43.000000000 -0400
+@@ -68,8 +68,44 @@
+ */
+ #include "ping_common.h"
+
+-#include <linux/in6.h>
+-#include <linux/ipv6.h>
++struct ipv6_rt_hdr {
++ __u8 nexthdr;
++ __u8 hdrlen;
++ __u8 type;
++ __u8 segments_left;
++
++ /*
++ * type specific data
++ * variable length field
++ */
++};
++
++struct rt0_hdr {
++ struct ipv6_rt_hdr rt_hdr;
++ __u32 bitmap; /* strict/loose bit map */
++ struct in6_addr addr[0];
++
++#define rt0_type rt_hdr.type;
++};
++#define IPV6_SRCRT_TYPE_0 0 /* IPv6 type 0 Routing Header */
++struct ipv6hdr {
++#if defined(__LITTLE_ENDIAN)
++ __u8 priority:4,
++ version:4;
++#elif defined(__BIG_ENDIAN)
++ __u8 version:4,
++ priority:4;
++#endif
++ __u8 flow_lbl[3];
++
++ __u16 payload_len;
++ __u8 nexthdr;
++ __u8 hop_limit;
++
++ struct in6_addr saddr;
++ struct in6_addr daddr;
++};
++
+ #include <linux/icmpv6.h>
+
+ #define BIT_CLEAR(nr, addr) do { ((__u32 *)(addr))[(nr) >> 5] &= ~(1U << ((nr) & 31)); } while(0)
+diff -urN iputils/ping.c iputils.new/ping.c
+--- iputils/ping.c 2003-09-10 17:27:48.000000000 -0400
++++ iputils.new/ping.c 2003-09-10 17:18:16.000000000 -0400
+@@ -60,8 +60,8 @@
+
+ #include "ping_common.h"
+
++#include <linux/icmp.h>
+ #include <netinet/ip.h>
+-#include <netinet/ip_icmp.h>
+
+
+ #define MAXIPLEN 60
+diff -urN iputils/ping_common.h iputils.new/ping_common.h
+--- iputils/ping_common.h 2002-09-20 11:08:11.000000000 -0400
++++ iputils.new/ping_common.h 2003-09-10 17:16:16.000000000 -0400
+@@ -19,6 +19,7 @@
+
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
++#include <linux/types.h>
+ #include <linux/errqueue.h>
+
+ #include "SNAPSHOT.h"
+diff -urN iputils/tftpd.c iputils.new/tftpd.c
+--- iputils/tftpd.c 2002-01-23 19:31:41.000000000 -0500
++++ iputils.new/tftpd.c 2003-09-10 09:39:45.000000000 -0400
+@@ -57,7 +57,6 @@
+
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+-#include <linux/in6.h>
+ #include <netdb.h>
+
+ #include <setjmp.h>
+diff -urN iputils/tracepath6.c iputils.new/tracepath6.c
+--- iputils/tracepath6.c 2001-09-01 22:03:46.000000000 -0400
++++ iputils.new/tracepath6.c 2003-09-10 09:40:18.000000000 -0400
+@@ -14,8 +14,7 @@
+ #include <unistd.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+-
+-#include <linux/in6.h>
++#include <linux/types.h>
+ #include <linux/errqueue.h>
+ #include <errno.h>
+ #include <string.h>
+diff -urN iputils/tracepath.c iputils.new/tracepath.c
+--- iputils/tracepath.c 2002-02-22 19:10:59.000000000 -0500
++++ iputils.new/tracepath.c 2003-09-10 06:14:35.000000000 -0400
+@@ -13,6 +13,7 @@
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <sys/socket.h>
++#include <linux/types.h>
+ #include <linux/errqueue.h>
+ #include <errno.h>
+ #include <string.h>
+diff -urN iputils/traceroute6.c iputils.new/traceroute6.c
+--- iputils/traceroute6.c 2002-09-20 11:44:22.000000000 -0400
++++ iputils.new/traceroute6.c 2003-09-10 10:12:47.000000000 -0400
+@@ -246,9 +246,24 @@
+ #include <netinet/ip_icmp.h>
+ #include <netinet/udp.h>
+
+-#include <linux/ipv6.h>
+-#include <linux/in6.h>
++#include <linux/types.h>
++struct ipv6hdr {
++#if defined(__LITTLE_ENDIAN)
++ __u8 priority:4,
++ version:4;
++#elif defined(__BIG_ENDIAN)
++ __u8 version:4,
++ priority:4;
++#endif
++ __u8 flow_lbl[3];
++
++ __u16 payload_len;
++ __u8 nexthdr;
++ __u8 hop_limit;
+
++ struct in6_addr saddr;
++ struct in6_addr daddr;
++};
+ #include <linux/icmpv6.h>
+
+ #include <arpa/inet.h>
--- /dev/null
+--- iputils/doc/Makefile.rh7 2002-02-23 01:17:57.000000000 +0100
++++ iputils/doc/Makefile 2004-05-12 14:55:16.724448173 +0200
+@@ -2,7 +2,7 @@
+ HTMLFILES=$(subst .sgml,.html,$(SGMLFILES)) index.html
+ MANFILES=$(subst .sgml,.8,$(SGMLFILES))
+
+-all: html
++all:
+
+ html: $(HTMLFILES) iputils.html
+
+--- iputils/Makefile.rh7 2002-09-20 20:23:55.000000000 +0200
++++ iputils/Makefile 2004-05-12 15:08:25.638310270 +0200
+@@ -24,14 +24,14 @@
+ CC=gcc
+ # What a pity, all new gccs are buggy and -Werror does not work. Sigh.
+ #CCOPT=-D_GNU_SOURCE -O2 -Wstrict-prototypes -Wall -g -Werror
+-CCOPT=-D_GNU_SOURCE -O2 -Wstrict-prototypes -Wall -g
+-CFLAGS=$(CCOPT) $(GLIBCFIX) -I$(KERNEL_INCLUDE) -I../include $(DEFINES)
++#CCOPT=-D_GNU_SOURCE -O2 -Wstrict-prototypes -Wall -g
++#CFLAGS=$(CCOPT) $(DEFINES)
+
+ IPV4_TARGETS=tracepath ping clockdiff rdisc arping tftpd rarpd
+ IPV6_TARGETS=tracepath6 traceroute6 ping6
+ TARGETS=$(IPV4_TARGETS) $(IPV6_TARGETS)
+
+-all: check-kernel $(TARGETS)
++all: $(TARGETS)
+
+
+ tftpd: tftpd.o tftpsubs.o
--- /dev/null
+diff -ru iputils/include-glibc/netinet/in.h iputils-clean/include-glibc/netinet/in.h
+--- iputils/include-glibc/netinet/in.h 2000-06-18 14:57:25.000000000 -0400
++++ iputils-clean/include-glibc/netinet/in.h 2003-09-03 11:21:55.000000000 -0400
+@@ -8,4 +8,45 @@
+
+ #define SOL_IP 0
+
+-#endif /* netinet/in.h */
++/* Functions to convert between host and network byte order.
++
++ Please note that these functions normally take `unsigned long int' or
++ `unsigned short int' values as arguments and also return them. But
++ this was a short-sighted decision since on different systems the types
++ may have different representations but the values are always the same. */
++
++extern u_int32_t ntohl (u_int32_t __netlong) __THROW __attribute__ ((__const__));
++extern u_int16_t ntohs (u_int16_t __netshort)
++ __THROW __attribute__ ((__const__));
++extern u_int32_t htonl (u_int32_t __hostlong)
++ __THROW __attribute__ ((__const__));
++extern u_int16_t htons (u_int16_t __hostshort)
++ __THROW __attribute__ ((__const__));
++
++#include <endian.h>
++
++/* Get machine dependent optimized versions of byte swapping functions. */
++#include <bits/byteswap.h>
++
++#ifdef __OPTIMIZE__
++/* We can optimize calls to the conversion functions. Either nothing has
++ to be done or we are using directly the byte-swapping functions which
++ often can be inlined. */
++# if __BYTE_ORDER == __BIG_ENDIAN
++/* The host byte order is the same as network byte order,
++ so these functions are all just identity. */
++# define ntohl(x) (x)
++# define ntohs(x) (x)
++# define htonl(x) (x)
++# define htons(x) (x)
++# else
++# if __BYTE_ORDER == __LITTLE_ENDIAN
++# define ntohl(x) __bswap_32 (x)
++# define ntohs(x) __bswap_16 (x)
++# define htonl(x) __bswap_32 (x)
++# define htons(x) __bswap_16 (x)
++# endif
++# endif
++#endif
++
++#endif /* netinet/in.h */
+diff -ru iputils/ping6.c iputils-clean/ping6.c
+--- iputils/ping6.c 2003-09-03 11:22:46.000000000 -0400
++++ iputils-clean/ping6.c 2003-09-03 11:15:42.000000000 -0400
+@@ -879,7 +879,7 @@
+ once = 1;
+
+ /* Patch bpflet for current identifier. */
+- insns[1] = (struct sock_filter)BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __constant_htons(ident), 0, 1);
++ insns[1] = (struct sock_filter)BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(ident), 0, 1);
+
+ if (setsockopt(icmp_sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)))
+ perror("WARNING: failed to install socket filter\n");
+diff -ru iputils/ping.c iputils-clean/ping.c
+--- iputils/ping.c 2003-09-03 11:22:46.000000000 -0400
++++ iputils-clean/ping.c 2003-09-03 11:15:26.000000000 -0400
+@@ -1196,7 +1196,7 @@
+ once = 1;
+
+ /* Patch bpflet for current identifier. */
+- insns[2] = (struct sock_filter)BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __constant_htons(ident), 0, 1);
++ insns[2] = (struct sock_filter)BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(ident), 0, 1);
+
+ if (setsockopt(icmp_sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)))
+ perror("WARNING: failed to install socket filter\n");
--- /dev/null
+diff --git a/src/perl/Makefile.PL b/src/perl/Makefile.PL
+index 38d5390..62016ca 100644
+--- a/src/perl/Makefile.PL
++++ b/src/perl/Makefile.PL
+@@ -11,6 +11,7 @@ WriteMakefile(
+ LIBS => ['-lloc'],
+ DEFINE => '', # e.g., '-DHAVE_SOMETHING'
+ INC => '-I. -I../../',
++ CCFLAGS => '-D_REENTRANT -D_GNU_SOURCE -O2 -pipe -Wall -fexceptions -fPIC -march=i586 -mindirect-branch=thunk -mfunction-return=thunk -mtune=generic -fomit-frame-pointer -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector -fwrapv -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
+ # Un-comment this if you add C files to link with later:
+ # OBJECT => '$(O_FILES)', # link all the C files too
+ );
--- /dev/null
+diff -Naur linux-3.10.10/drivers/net/usb/smsc95xx.c linux-c1af7c6db316763b9dce7137495cb9ada8fa17b4/drivers/net/usb/smsc95xx.c
+--- linux-3.10.10/drivers/net/usb/smsc95xx.c 2013-08-29 18:47:51.000000000 +0200
++++ linux-c1af7c6db316763b9dce7137495cb9ada8fa17b4/drivers/net/usb/smsc95xx.c 2013-08-30 20:12:54.000000000 +0200
+@@ -61,6 +61,7 @@
+ #define SUSPEND_SUSPEND3 (0x08)
+ #define SUSPEND_ALLMODES (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \
+ SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3)
++#define MAC_ADDR_LEN (6)
+
+ struct smsc95xx_priv {
+ u32 mac_cr;
+@@ -76,6 +77,10 @@
+ module_param(turbo_mode, bool, 0644);
+ MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction");
+
++static char *macaddr = ":";
++module_param(macaddr, charp, 0);
++MODULE_PARM_DESC(macaddr, "MAC address");
++
+ static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index,
+ u32 *data, int in_pm)
+ {
+@@ -765,8 +770,59 @@
+ return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
+ }
+
++/* Check the macaddr module parameter for a MAC address */
++static int smsc95xx_is_macaddr_param(struct usbnet *dev, u8 *dev_mac)
++{
++ int i, j, got_num, num;
++ u8 mtbl[MAC_ADDR_LEN];
++
++ if (macaddr[0] == ':')
++ return 0;
++
++ i = 0;
++ j = 0;
++ num = 0;
++ got_num = 0;
++ while (j < MAC_ADDR_LEN) {
++ if (macaddr[i] && macaddr[i] != ':') {
++ got_num++;
++ if ('0' <= macaddr[i] && macaddr[i] <= '9')
++ num = num * 16 + macaddr[i] - '0';
++ else if ('A' <= macaddr[i] && macaddr[i] <= 'F')
++ num = num * 16 + 10 + macaddr[i] - 'A';
++ else if ('a' <= macaddr[i] && macaddr[i] <= 'f')
++ num = num * 16 + 10 + macaddr[i] - 'a';
++ else
++ break;
++ i++;
++ } else if (got_num == 2) {
++ mtbl[j++] = (u8) num;
++ num = 0;
++ got_num = 0;
++ i++;
++ } else {
++ break;
++ }
++ }
++
++ if (j == MAC_ADDR_LEN) {
++ netif_dbg(dev, ifup, dev->net, "Overriding MAC address with: "
++ "%02x:%02x:%02x:%02x:%02x:%02x\n", mtbl[0], mtbl[1], mtbl[2],
++ mtbl[3], mtbl[4], mtbl[5]);
++ for (i = 0; i < MAC_ADDR_LEN; i++)
++ dev_mac[i] = mtbl[i];
++ return 1;
++ } else {
++ return 0;
++ }
++}
++
+ static void smsc95xx_init_mac_address(struct usbnet *dev)
+ {
++ /* Check module parameters */
++ if (smsc95xx_is_macaddr_param(dev, dev->net->dev_addr))
++ return;
++
+ /* try reading mac address from EEPROM */
+ if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN,
+ dev->net->dev_addr) == 0) {
--- /dev/null
+diff -Naur linux-3.10.10.org/drivers/crypto/mv_cesa.c linux-3.10.10/drivers/crypto/mv_cesa.c
+--- linux-3.10.10.org/drivers/crypto/mv_cesa.c 2013-08-29 18:47:51.000000000 +0200
++++ linux-3.10.10/drivers/crypto/mv_cesa.c 2013-09-04 13:06:35.000000000 +0200
+@@ -1120,6 +1120,7 @@
+ else
+ printk(KERN_WARNING MV_CESA "Could not register sha1 driver\n");
+
++/*
+ ret = crypto_register_ahash(&mv_hmac_sha1_alg);
+ if (ret == 0) {
+ cpg->has_hmac_sha1 = 1;
+@@ -1127,6 +1128,7 @@
+ printk(KERN_WARNING MV_CESA
+ "Could not register hmac-sha1 driver\n");
+ }
++*/
+
+ return 0;
+ err_unreg_ecb:
--- /dev/null
+diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
+index f8f0156..42a0702 100644
+--- a/drivers/net/wireless/Kconfig
++++ b/drivers/net/wireless/Kconfig
+@@ -51,6 +51,14 @@ config LIBERTAS_THINFIRM_USB
+ ---help---
+ A driver for Marvell Libertas 8388 USB devices using thinfirm.
+
++config LIBERTAS_UAP
++ tristate "Marvell 8xxx Libertas UAP"
++ depends on MAC80211
++ depends on MMC
++ select FW_LOADER
++ ---help---
++ Driver for Marvell Libertas 8xxx micro AP.
++
+ config AIRO
+ tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards"
+ depends on ISA_DMA_API && (PCI || BROKEN)
+diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
+index 67156ef..475a1b3 100644
+--- a/drivers/net/wireless/Makefile
++++ b/drivers/net/wireless/Makefile
+@@ -37,6 +37,8 @@ obj-$(CONFIG_LIBERTAS) += libertas/
+
+ obj-$(CONFIG_LIBERTAS_THINFIRM) += libertas_tf/
+
++obj-$(CONFIG_LIBERTAS_UAP) += libertas_uap/
++
+ obj-$(CONFIG_ADM8211) += adm8211.o
+
+ obj-$(CONFIG_MWL8K) += mwl8k.o
+diff --git a/drivers/net/wireless/libertas_uap/Makefile b/drivers/net/wireless/libertas_uap/Makefile
+new file mode 100644
+index 0000000..821f2a4
+--- /dev/null
++++ b/drivers/net/wireless/libertas_uap/Makefile
+@@ -0,0 +1,6 @@
++obj-$(CONFIG_LIBERTAS_UAP) += uap8xxx.o
++
++uap8xxx-y += uap_main.o uap_sdio_mmc.o
++uap8xxx-$(CONFIG_PROC_FS) += uap_proc.o uap_debug.o
++
++EXTRA_CFLAGS += -DFPNUM='"52"' -DPXA3XX_DMA_ALIGN -DDEBUG_LEVEL1
+diff --git a/drivers/net/wireless/libertas_uap/uap_debug.c b/drivers/net/wireless/libertas_uap/uap_debug.c
+new file mode 100644
+index 0000000..a2f6dc9
+--- /dev/null
++++ b/drivers/net/wireless/libertas_uap/uap_debug.c
+@@ -0,0 +1,260 @@
++/** @file uap_debug.c
++ * @brief This file contains functions for debug proc file.
++ *
++ * Copyright (C) 2008-2009, Marvell International Ltd.
++ *
++ * This software file (the "File") is distributed by Marvell International
++ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
++ * (the "License"). You may use, redistribute and/or modify this File in
++ * accordance with the terms and conditions of the License, a copy of which
++ * is available along with the File in the gpl.txt file or by writing to
++ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++ *
++ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
++ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
++ * this warranty disclaimer.
++ *
++ */
++#ifdef CONFIG_PROC_FS
++#include "uap_headers.h"
++
++/********************************************************
++ Local Variables
++********************************************************/
++
++#define item_size(n) (sizeof ((uap_adapter *)0)->n)
++#define item_addr(n) ((u32) &((uap_adapter *)0)->n)
++
++#define item_dbg_size(n) (sizeof (((uap_adapter *)0)->dbg.n))
++#define item_dbg_addr(n) ((u32) &(((uap_adapter *)0)->dbg.n))
++
++#define item_dev_size(n) (sizeof ((uap_dev_t *)0)->n)
++#define item_dev_addr(n) ((u32) &((uap_dev_t *)0)->n)
++
++/** MicroAp device offset */
++#define OFFSET_UAP_DEV 0x01
++/** Bluetooth adapter offset */
++#define OFFSET_UAP_ADAPTER 0x02
++
++struct debug_data
++{
++ /** Name */
++ char name[32];
++ /** Size */
++ u32 size;
++ /** Address */
++ u32 addr;
++ /** Offset */
++ u32 offset;
++ /** Flag */
++ u32 flag;
++};
++
++/* To debug any member of uap_adapter, simply add one line here.
++ */
++static struct debug_data items[] = {
++ {"cmd_sent", item_dev_size(cmd_sent), 0, item_dev_addr(cmd_sent),
++ OFFSET_UAP_DEV},
++ {"data_sent", item_dev_size(data_sent), 0, item_dev_addr(data_sent),
++ OFFSET_UAP_DEV},
++ {"IntCounter", item_size(IntCounter), 0, item_addr(IntCounter),
++ OFFSET_UAP_ADAPTER},
++ {"cmd_pending", item_size(cmd_pending), 0, item_addr(cmd_pending),
++ OFFSET_UAP_ADAPTER},
++ {"num_cmd_h2c_fail", item_dbg_size(num_cmd_host_to_card_failure), 0,
++ item_dbg_addr(num_cmd_host_to_card_failure), OFFSET_UAP_ADAPTER},
++ {"num_tx_h2c_fail", item_dbg_size(num_tx_host_to_card_failure), 0,
++ item_dbg_addr(num_tx_host_to_card_failure), OFFSET_UAP_ADAPTER},
++ {"psmode", item_size(psmode), 0, item_addr(psmode), OFFSET_UAP_ADAPTER},
++ {"ps_state", item_size(ps_state), 0, item_addr(ps_state),
++ OFFSET_UAP_ADAPTER},
++#ifdef DEBUG_LEVEL1
++ {"drvdbg", sizeof(drvdbg), (u32) & drvdbg, 0, 0}
++#endif
++};
++
++static int num_of_items = sizeof(items) / sizeof(items[0]);
++
++/********************************************************
++ Global Variables
++********************************************************/
++
++/********************************************************
++ Local Functions
++********************************************************/
++/**
++ * @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 int uap_debug_proc_show(struct seq_file *s, void *data) {
++ int val = 0;
++ int i;
++
++ struct debug_data *d = (struct debug_data *)s->private;
++
++ if (MODULE_GET == 0)
++ return UAP_STATUS_FAILURE;
++
++ 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);
++
++ seq_printf(s, "%s=%d\n", d[i].name, val);
++ }
++ MODULE_PUT;
++ return 0;
++}
++
++static int uap_debug_proc_open(struct inode* inode, struct file* file) {
++ return single_open(file, uap_debug_proc_show, PDE_DATA(inode));
++}
++
++/**
++ * @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 uap_debug_proc_write(struct file *f, const char __user *buf, size_t cnt, loff_t *data) {
++ int r, i;
++ char *pdata;
++ char *p;
++ char *p0;
++ char *p1;
++ char *p2;
++ struct debug_data *d = (struct debug_data *)PDE_DATA(file_inode(f));
++
++ if (MODULE_GET == 0)
++ return UAP_STATUS_FAILURE;
++
++ pdata = (char *) kmalloc(cnt, GFP_KERNEL);
++ if (pdata == NULL) {
++ MODULE_PUT;
++ return 0;
++ }
++
++ if (copy_from_user(pdata, buf, cnt)) {
++ PRINTM(INFO, "Copy from user failed\n");
++ kfree(pdata);
++ MODULE_PUT;
++ 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 = string_to_number(p2);
++ 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;
++ break;
++ } while (TRUE);
++ }
++ kfree(pdata);
++#ifdef DEBUG_LEVEL1
++ printk(KERN_ALERT "drvdbg = 0x%x\n", drvdbg);
++ printk(KERN_ALERT "INFO (%08lx) %s\n", DBG_INFO,
++ (drvdbg & DBG_INFO) ? "X" : "");
++ printk(KERN_ALERT "WARN (%08lx) %s\n", DBG_WARN,
++ (drvdbg & DBG_WARN) ? "X" : "");
++ printk(KERN_ALERT "ENTRY (%08lx) %s\n", DBG_ENTRY,
++ (drvdbg & DBG_ENTRY) ? "X" : "");
++ printk(KERN_ALERT "CMD_D (%08lx) %s\n", DBG_CMD_D,
++ (drvdbg & DBG_CMD_D) ? "X" : "");
++ printk(KERN_ALERT "DAT_D (%08lx) %s\n", DBG_DAT_D,
++ (drvdbg & DBG_DAT_D) ? "X" : "");
++ printk(KERN_ALERT "CMND (%08lx) %s\n", DBG_CMND,
++ (drvdbg & DBG_CMND) ? "X" : "");
++ printk(KERN_ALERT "DATA (%08lx) %s\n", DBG_DATA,
++ (drvdbg & DBG_DATA) ? "X" : "");
++ printk(KERN_ALERT "ERROR (%08lx) %s\n", DBG_ERROR,
++ (drvdbg & DBG_ERROR) ? "X" : "");
++ printk(KERN_ALERT "FATAL (%08lx) %s\n", DBG_FATAL,
++ (drvdbg & DBG_FATAL) ? "X" : "");
++ printk(KERN_ALERT "MSG (%08lx) %s\n", DBG_MSG,
++ (drvdbg & DBG_MSG) ? "X" : "");
++#endif
++ MODULE_PUT;
++ return cnt;
++}
++
++static const struct file_operations uap_debug_proc_fops = {
++ .owner = THIS_MODULE,
++ .open = uap_debug_proc_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++ .write = uap_debug_proc_write,
++};
++
++/********************************************************
++ Global Functions
++********************************************************/
++/**
++ * @brief create debug proc file
++ *
++ * @param priv pointer uap_private
++ * @param dev pointer net_device
++ * @return N/A
++ */
++void
++uap_debug_entry(uap_private * priv, struct net_device *dev)
++{
++ int i;
++
++ if (priv->proc_entry == NULL)
++ return;
++
++ for (i = 0; i < num_of_items; i++) {
++ if (items[i].flag & OFFSET_UAP_ADAPTER)
++ items[i].addr = items[i].offset + (u32) priv->adapter;
++ if (items[i].flag & OFFSET_UAP_DEV)
++ items[i].addr = items[i].offset + (u32) & priv->uap_dev;
++ }
++ proc_create_data("debug", 0644, priv->proc_entry, &uap_debug_proc_fops,
++ &items[0]);
++}
++
++/**
++ * @brief remove proc file
++ *
++ * @param priv pointer uap_private
++ * @return N/A
++ */
++void
++uap_debug_remove(uap_private * priv)
++{
++ remove_proc_entry("debug", priv->proc_entry);
++}
++
++#endif
+diff --git a/drivers/net/wireless/libertas_uap/uap_drv.h b/drivers/net/wireless/libertas_uap/uap_drv.h
+new file mode 100644
+index 0000000..5aa009f
+--- /dev/null
++++ b/drivers/net/wireless/libertas_uap/uap_drv.h
+@@ -0,0 +1,667 @@
++/** @file uap_drv.h
++ * @brief This file contains Linux OS related definitions and
++ * declarations, uAP driver
++ *
++ * Copyright (C) 2008-2009, Marvell International Ltd.
++ *
++ * This software file (the "File") is distributed by Marvell International
++ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
++ * (the "License"). You may use, redistribute and/or modify this File in
++ * accordance with the terms and conditions of the License, a copy of which
++ * is available along with the File in the gpl.txt file or by writing to
++ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++ *
++ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
++ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
++ * this warranty disclaimer.
++ *
++ */
++
++#ifndef _UAP_DRV_H
++#define _UAP_DRV_H
++
++/** Driver release version */
++#define DRIVER_VERSION "26146"
++
++/** True */
++#ifndef TRUE
++#define TRUE 1
++#endif
++/** False */
++#ifndef FALSE
++#define FALSE 0
++#endif
++
++/** Bit definitions */
++#ifndef BIT
++#define BIT(x) (1UL << (x))
++#endif
++
++/** Dma addresses are 32-bits wide. */
++#ifndef __ATTRIB_ALIGN__
++#define __ATTRIB_ALIGN__ __attribute__((aligned(4)))
++#endif
++
++/** attribute pack */
++#ifndef __ATTRIB_PACK__
++#define __ATTRIB_PACK__ __attribute__ ((packed))
++#endif
++
++/** Debug Macro definition*/
++#ifdef DEBUG_LEVEL1
++
++extern u32 drvdbg;
++
++/** Debug message control bit definition for drvdbg */
++/** Debug message */
++#define DBG_MSG BIT(0)
++/** Debug fatal message */
++#define DBG_FATAL BIT(1)
++/** Debug error message */
++#define DBG_ERROR BIT(2)
++/** Debug data message */
++#define DBG_DATA BIT(3)
++/** Debug command message */
++#define DBG_CMND BIT(4)
++
++/** Debug data */
++#define DBG_DAT_D BIT(16)
++/** Debug command */
++#define DBG_CMD_D BIT(17)
++
++/** Debug entry */
++#define DBG_ENTRY BIT(28)
++/** Debug warning */
++#define DBG_WARN BIT(29)
++/** Debug info */
++#define DBG_INFO BIT(30)
++
++/** Print info */
++#define PRINTM_INFO(msg...) {if (drvdbg & DBG_INFO) printk(KERN_DEBUG msg);}
++/** Print warn message */
++#define PRINTM_WARN(msg...) {if (drvdbg & DBG_WARN) printk(KERN_DEBUG msg);}
++/** Print entry */
++#define PRINTM_ENTRY(msg...) {if (drvdbg & DBG_ENTRY) printk(KERN_DEBUG msg);}
++/** Print cmd_d */
++#define PRINTM_CMD_D(msg...) {if (drvdbg & DBG_CMD_D) printk(KERN_DEBUG msg);}
++/** Print data_d */
++#define PRINTM_DAT_D(msg...) {if (drvdbg & DBG_DAT_D) printk(KERN_DEBUG msg);}
++/** Print command */
++#define PRINTM_CMND(msg...) {if (drvdbg & DBG_CMND) printk(KERN_DEBUG msg);}
++/** Print data */
++#define PRINTM_DATA(msg...) {if (drvdbg & DBG_DATA) printk(KERN_DEBUG msg);}
++/** Print error message */
++#define PRINTM_ERROR(msg...) {if (drvdbg & DBG_ERROR) printk(KERN_DEBUG msg);}
++/** Print fatal message */
++#define PRINTM_FATAL(msg...) {if (drvdbg & DBG_FATAL) printk(KERN_DEBUG msg);}
++/** Print message */
++#define PRINTM_MSG(msg...) {if (drvdbg & DBG_MSG) printk(KERN_ALERT msg);}
++/** Print level */
++#define PRINTM(level,msg...) PRINTM_##level(msg)
++
++#else
++
++#define PRINTM(level,msg...) do {} while (0)
++
++#endif /* DEBUG_LEVEL1 */
++
++/** Wait until a condition becomes true */
++#define ASSERT(cond) \
++do { \
++ if (!(cond)) \
++ PRINTM(INFO, "ASSERT: %s, %s:%i\n", \
++ __FUNCTION__, __FILE__, __LINE__); \
++} while(0)
++
++/** Log enrty point for debugging */
++#define ENTER() PRINTM(ENTRY, "Enter: %s, %s:%i\n", __FUNCTION__, \
++ __FILE__, __LINE__)
++/** Log exit point for debugging */
++#define LEAVE() PRINTM(ENTRY, "Leave: %s, %s:%i\n", __FUNCTION__, \
++ __FILE__, __LINE__)
++
++#ifdef DEBUG_LEVEL1
++/** Dump buffer length */
++#define DBG_DUMP_BUF_LEN 64
++/** Maximum dump per line */
++#define MAX_DUMP_PER_LINE 16
++/** Data dump length */
++#define DATA_DUMP_LEN 32
++
++static inline void
++hexdump(char *prompt, u8 * buf, int len)
++{
++ int i;
++ char dbgdumpbuf[DBG_DUMP_BUF_LEN];
++ char *ptr = dbgdumpbuf;
++
++ printk(KERN_DEBUG "%s:\n", prompt);
++ for (i = 1; i <= len; i++) {
++ ptr += sprintf(ptr, "%02x ", *buf);
++ buf++;
++ if (i % MAX_DUMP_PER_LINE == 0) {
++ *ptr = 0;
++ printk(KERN_DEBUG "%s\n", dbgdumpbuf);
++ ptr = dbgdumpbuf;
++ }
++ }
++ if (len % MAX_DUMP_PER_LINE) {
++ *ptr = 0;
++ printk(KERN_DEBUG "%s\n", dbgdumpbuf);
++ }
++}
++
++/** Debug command */
++#define DBG_HEXDUMP_CMD_D(x,y,z) {if (drvdbg & DBG_CMD_D) hexdump(x,y,z);}
++/** Debug data */
++#define DBG_HEXDUMP_DAT_D(x,y,z) {if (drvdbg & DBG_DAT_D) hexdump(x,y,z);}
++/** Debug hexdump */
++#define DBG_HEXDUMP(level,x,y,z) DBG_HEXDUMP_##level(x,y,z)
++/** hexdump */
++#define HEXDUMP(x,y,z) {if (drvdbg & DBG_INFO) hexdump(x,y,z);}
++#else
++/** Do nothing since debugging is not turned on */
++#define DBG_HEXDUMP(level,x,y,z) do {} while (0)
++/** Do nothing since debugging is not turned on */
++#define HEXDUMP(x,y,z) do {} while (0)
++#endif
++
++/**
++ * Typedefs
++ */
++/** Unsigned char */
++typedef u8 BOOLEAN;
++
++/*
++ * OS macro definitions
++ */
++/** OS macro to get time */
++#define os_time_get() jiffies
++
++/** OS macro to update transfer start time */
++#define UpdateTransStart(dev) { \
++ dev->trans_start = jiffies; \
++}
++
++/** Try to get a reference to the module */
++#define MODULE_GET try_module_get(THIS_MODULE)
++/** Decrease module reference count */
++#define MODULE_PUT module_put(THIS_MODULE)
++
++/** OS macro to initialize semaphore */
++#define OS_INIT_SEMAPHORE(x) sema_init(x,1)
++/** OS macro to acquire blocking semaphore */
++#define OS_ACQ_SEMAPHORE_BLOCK(x) down_interruptible(x)
++/** OS macro to acquire non-blocking semaphore */
++#define OS_ACQ_SEMAPHORE_NOBLOCK(x) down_trylock(x)
++/** OS macro to release semaphore */
++#define OS_REL_SEMAPHORE(x) up(x)
++
++static inline void
++os_sched_timeout(u32 millisec)
++{
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule_timeout((millisec * HZ) / 1000);
++}
++
++/** Maximum size of ethernet packet */
++#define MRVDRV_MAXIMUM_ETH_PACKET_SIZE 1514
++
++/** Maximum size of multicast list */
++#define MRVDRV_MAX_MULTICAST_LIST_SIZE 32
++
++/** Find minimum */
++#ifndef MIN
++#define MIN(a,b) ((a) < (b) ? (a) : (b))
++#endif
++
++/** Find maximum */
++#ifndef MAX
++#define MAX(a,b) ((a) > (b) ? (a) : (b))
++#endif
++
++/** Find number of elements */
++#ifndef NELEMENTS
++#define NELEMENTS(x) (sizeof(x)/sizeof(x[0]))
++#endif
++
++/** Buffer Constants */
++
++/** Size of command buffer */
++#define MRVDRV_SIZE_OF_CMD_BUFFER (2 * 1024)
++
++/** Length of device length */
++#define DEV_NAME_LEN 32
++
++/** Length of ethernet address */
++#ifndef ETH_ALEN
++#define ETH_ALEN 6
++#endif
++
++/** Default watchdog timeout */
++#define MRVDRV_DEFAULT_WATCHDOG_TIMEOUT (2 * HZ)
++
++/** Success */
++#define UAP_STATUS_SUCCESS (0)
++/** Failure */
++#define UAP_STATUS_FAILURE (-1)
++/** Not accepted */
++#define UAP_STATUS_NOT_ACCEPTED (-2)
++
++/** Max loop count (* 100ms) for waiting device ready at init time */
++#define MAX_WAIT_DEVICE_READY_COUNT 50
++
++/** Tx high watermark. Stop Tx queue after this is crossed */
++#define TX_HIGH_WATERMARK 4
++/** Tx low watermark. Restart Tx queue after this is crossed */
++#define TX_LOW_WATERMARK 2
++
++/** Netlink protocol number */
++#define NETLINK_MARVELL (MAX_LINKS - 1)
++/** Netlink maximum payload size */
++#define NL_MAX_PAYLOAD 1024
++/** Netlink multicast group number */
++#define NL_MULTICAST_GROUP 1
++
++/** 20 seconds */
++#define MRVDRV_TIMER_20S 20000
++
++/** Host Command option for wait till Send */
++#define HostCmd_OPTION_WAITFORSEND 0x0001
++/** Host Command option for wait for RSP */
++#define HostCmd_OPTION_WAITFORRSP 0x0002
++/** Host Command option for wait for RSP or Timeout */
++#define HostCmd_OPTION_WAITFORRSP_TIMEOUT 0x0003
++/** Host Command option for wait for RSP of sleep confirm */
++#define HostCmd_OPTION_WAITFORRSP_SLEEPCONFIRM 0x0004
++
++/** Sleep until a condition gets true or a timeout elapses */
++#define os_wait_interruptible_timeout(waitq, cond, timeout) \
++ wait_event_interruptible_timeout(waitq, cond, ((timeout) * HZ / 1000))
++
++/** Private command ID to Host command */
++#define UAPHOSTCMD (SIOCDEVPRIVATE + 1)
++
++/** Private command ID to Power Mode */
++#define UAP_POWER_MODE (SIOCDEVPRIVATE + 3)
++/** sleep_param */
++typedef struct _ps_sleep_param
++{
++ /** control bitmap */
++ u32 ctrl_bitmap;
++ /** minimum sleep period (micro second) */
++ u32 min_sleep;
++ /** maximum sleep period (micro second) */
++ u32 max_sleep;
++} ps_sleep_param;
++
++/** inactivity sleep_param */
++typedef struct _inact_sleep_param
++{
++ /** inactivity timeout (micro second) */
++ u32 inactivity_to;
++ /** miniumu awake period (micro second) */
++ u32 min_awake;
++ /** maximum awake period (micro second) */
++ u32 max_awake;
++} inact_sleep_param;
++
++/** flag for ps mode */
++#define PS_FLAG_PS_MODE 1
++/** flag for sleep param */
++#define PS_FLAG_SLEEP_PARAM 2
++/** flag for inactivity sleep param */
++#define PS_FLAG_INACT_SLEEP_PARAM 4
++
++/** Disable power mode */
++#define PS_MODE_DISABLE 0
++/** Enable periodic dtim ps */
++#define PS_MODE_PERIODIC_DTIM 1
++/** Enable inactivity ps */
++#define PS_MODE_INACTIVITY 2
++
++/** sleep parameter */
++#define SLEEP_PARAMETER 1
++/** inactivity sleep parameter */
++#define INACTIVITY_SLEEP_PARAMETER 2
++/** ps_mgmt */
++typedef struct _ps_mgmt
++{
++ /** flags for valid field */
++ u16 flags;
++ /** power mode */
++ u16 ps_mode;
++ /** sleep param */
++ ps_sleep_param sleep_param;
++ /** inactivity sleep param */
++ inact_sleep_param inact_param;
++} ps_mgmt;
++
++/** Semaphore structure */
++typedef struct semaphore SEMAPHORE;
++
++/** Global Varibale Declaration */
++/** Private data structure of the device */
++typedef struct _uap_private uap_private;
++/** Adapter data structure of the device */
++typedef struct _uap_adapter uap_adapter;
++/** private structure */
++extern uap_private *uappriv;
++
++/** ENUM definition*/
++
++/** Hardware status codes */
++typedef enum _HARDWARE_STATUS
++{
++ HWReady,
++ HWInitializing,
++ HWReset,
++ HWClosing,
++ HWNotReady
++} HARDWARE_STATUS;
++
++/** info for debug purpose */
++typedef struct _uap_dbg
++{
++ /** Number of host to card command failures */
++ u32 num_cmd_host_to_card_failure;
++ /** Number of host to card Tx failures */
++ u32 num_tx_host_to_card_failure;
++} uap_dbg;
++
++/** Set thread state */
++#define OS_SET_THREAD_STATE(x) set_current_state(x)
++
++typedef struct
++{
++ /** Task */
++ struct task_struct *task;
++ /** Queue */
++ wait_queue_head_t waitQ;
++ /** PID */
++ pid_t pid;
++ /** Private structure */
++ void *priv;
++} uap_thread;
++
++static inline void
++uap_activate_thread(uap_thread * thr)
++{
++ /** Record the thread pid */
++ thr->pid = current->pid;
++
++ /** Initialize the wait queue */
++ init_waitqueue_head(&thr->waitQ);
++}
++
++static inline void
++uap_deactivate_thread(uap_thread * thr)
++{
++ thr->pid = 0;
++ return;
++}
++
++static inline void
++uap_create_thread(int (*uapfunc) (void *), uap_thread * thr, char *name)
++{
++ thr->task = kthread_run(uapfunc, thr, "%s", name);
++}
++
++static inline int
++uap_terminate_thread(uap_thread * thr)
++{
++ /* Check if the thread is active or not */
++ if (!thr->pid)
++ return -1;
++ kthread_stop(thr->task);
++ return 0;
++}
++
++/** Data structure for the Marvell uAP device */
++typedef struct _uap_dev
++{
++ /** device name */
++ char name[DEV_NAME_LEN];
++ /** card pointer */
++ void *card;
++ /** IO port */
++ u32 ioport;
++ /** Rx unit */
++ u8 rx_unit;
++ /** Data sent:
++ TRUE - Data is sent to fw, no Tx Done received
++ FALSE - Tx done received for previous Tx */
++ BOOLEAN data_sent;
++ /** CMD sent:
++ TRUE - CMD is sent to fw, no CMD Done received
++ FALSE - CMD done received for previous CMD */
++ BOOLEAN cmd_sent;
++ /** netdev pointer */
++ struct net_device *netdev;
++} uap_dev_t, *puap_dev_t;
++
++/** Private structure for the MV device */
++struct _uap_private
++{
++ /** Device open */
++ int open;
++
++ /** Device adapter structure */
++ uap_adapter *adapter;
++ /** Device structure */
++ uap_dev_t uap_dev;
++
++ /** Net device statistics structure */
++ struct net_device_stats stats;
++
++ /** Number of Tx timeouts */
++ u32 num_tx_timeout;
++
++ /** Media connection status */
++ BOOLEAN MediaConnected;
++
++#ifdef CONFIG_PROC_FS
++ struct proc_dir_entry *proc_uap;
++ struct proc_dir_entry *proc_entry;
++#endif /* CONFIG_PROC_FS */
++
++ /** Firmware helper */
++ const struct firmware *fw_helper;
++ /** Firmware */
++ const struct firmware *firmware;
++ /** Hotplug device */
++ struct device *hotplug_device;
++ /** thread to service interrupts */
++ uap_thread MainThread;
++ /** Driver lock */
++ spinlock_t driver_lock;
++ /** Driver lock flags */
++ ulong driver_flags;
++
++};
++
++/** PS_CMD_ConfirmSleep */
++typedef struct _PS_CMD_ConfirmSleep
++{
++ /** SDIO Length */
++ u16 SDLen;
++ /** SDIO Type */
++ u16 SDType;
++ /** Command */
++ u16 Command;
++ /** Size */
++ u16 Size;
++ /** Sequence number */
++ u16 SeqNum;
++ /** Result */
++ u16 Result;
++} __ATTRIB_PACK__ PS_CMD_ConfirmSleep, *PPS_CMD_ConfirmSleep;
++
++/** Wlan Adapter data structure*/
++struct _uap_adapter
++{
++ /** Power save confirm sleep command */
++ PS_CMD_ConfirmSleep PSConfirmSleep;
++ /** Device status */
++ HARDWARE_STATUS HardwareStatus;
++ /** Interrupt counter */
++ u32 IntCounter;
++ /** Tx packet queue */
++ struct sk_buff_head tx_queue;
++ /** Cmd packet queue */
++ struct sk_buff_head cmd_queue;
++ /** Command sequence number */
++ u16 SeqNum;
++ /** Command buffer */
++ u8 *CmdBuf;
++ /** cmd pending flag */
++ u8 cmd_pending;
++ /** cmd wait option */
++ u8 cmd_wait_option;
++ /** Command buffer length */
++ u32 CmdSize;
++ /** Command wait queue */
++ wait_queue_head_t cmdwait_q __ATTRIB_ALIGN__;
++ /** Command wait queue state flag */
++ u8 CmdWaitQWoken;
++ /** PnP support */
++ BOOLEAN SurpriseRemoved;
++ /** Debug */
++ uap_dbg dbg;
++ /** Netlink kernel socket */
++ struct sock *nl_sk;
++ /** Semaphore for CMD */
++ SEMAPHORE CmdSem;
++ /** Power Save mode */
++ u8 psmode;
++ /** Power Save state */
++ u8 ps_state;
++ /** Number of wakeup tries */
++ u32 WakeupTries;
++};
++
++static inline int
++os_upload_rx_packet(uap_private * priv, struct sk_buff *skb)
++{
++ skb->dev = priv->uap_dev.netdev;
++ skb->protocol = eth_type_trans(skb, priv->uap_dev.netdev);
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++ if (in_interrupt())
++ netif_rx(skb);
++ else
++ netif_rx_ni(skb);
++ return 0;
++}
++
++/*
++ * netif carrier_on/off and start(wake)/stop_queue handling
++ */
++static inline void
++os_carrier_on(uap_private * priv)
++{
++ if (!netif_carrier_ok(priv->uap_dev.netdev) &&
++ (priv->MediaConnected == TRUE)) {
++ netif_carrier_on(priv->uap_dev.netdev);
++ }
++}
++
++static inline void
++os_carrier_off(uap_private * priv)
++{
++ if (netif_carrier_ok(priv->uap_dev.netdev)) {
++ netif_carrier_off(priv->uap_dev.netdev);
++ }
++}
++
++static inline void
++os_start_queue(uap_private * priv)
++{
++ if (netif_queue_stopped(priv->uap_dev.netdev) &&
++ (priv->MediaConnected == TRUE)) {
++ netif_wake_queue(priv->uap_dev.netdev);
++ }
++}
++
++static inline void
++os_stop_queue(uap_private * priv)
++{
++ if (!netif_queue_stopped(priv->uap_dev.netdev)) {
++ netif_stop_queue(priv->uap_dev.netdev);
++ }
++}
++
++/** Interface specific header */
++#define INTF_HEADER_LEN 4
++
++/** headroom alignment for tx packet */
++#define HEADER_ALIGNMENT 8
++
++/** The number of times to try when polling for status bits */
++#define MAX_POLL_TRIES 100
++
++/** Length of SNAP header */
++#define MRVDRV_SNAP_HEADER_LEN 8
++
++/** Extra length of Tx packet buffer */
++#define EXTRA_LEN 36
++
++/** Buffer size for ethernet Tx packets */
++#define MRVDRV_ETH_TX_PACKET_BUFFER_SIZE \
++ (ETH_FRAME_LEN + sizeof(TxPD) + EXTRA_LEN)
++
++/** Buffer size for ethernet Rx packets */
++#define MRVDRV_ETH_RX_PACKET_BUFFER_SIZE \
++ (ETH_FRAME_LEN + sizeof(RxPD) \
++ + MRVDRV_SNAP_HEADER_LEN + EXTRA_LEN)
++
++/** Packet type: data, command & event */
++typedef enum _mv_type
++{
++ MV_TYPE_DAT = 0,
++ MV_TYPE_CMD = 1,
++ MV_TYPE_EVENT = 3
++} mv_type;
++
++/** Disable interrupt */
++#define OS_INT_DISABLE spin_lock_irqsave(&priv->driver_lock, priv->driver_flags)
++/** Enable interrupt */
++#define OS_INT_RESTORE spin_unlock_irqrestore(&priv->driver_lock, priv->driver_flags)
++
++int uap_process_rx_packet(uap_private * priv, struct sk_buff *skb);
++void uap_interrupt(uap_private * priv);
++uap_private *uap_add_card(void *card);
++int uap_remove_card(void *card);
++int uap_process_event(uap_private * priv, u8 * payload, uint len);
++int uap_soft_reset(uap_private * priv);
++int uap_process_sleep_confirm_resp(uap_private * priv, u8 * resp, int resp_len);
++
++#ifdef CONFIG_PROC_FS
++/** The proc fs interface */
++void uap_proc_entry(uap_private * priv, struct net_device *dev);
++void uap_proc_remove(uap_private * priv);
++int string_to_number(char *s);
++void uap_debug_entry(uap_private * priv, struct net_device *dev);
++void uap_debug_remove(uap_private * priv);
++#endif /* CONFIG_PROC_FS */
++
++int sbi_register(void);
++
++void sbi_unregister(void);
++int sbi_register_dev(uap_private * priv);
++int sbi_unregister_dev(uap_private * priv);
++int sbi_prog_fw_w_helper(uap_private *);
++
++int sbi_host_to_card(uap_private * priv, u8 * payload, u16 nb);
++int sbi_enable_host_int(uap_private * priv);
++int sbi_disable_host_int(uap_private * priv);
++
++int sbi_get_int_status(uap_private * priv, u8 * ireg);
++/** Check firmware status */
++int sbi_check_fw_status(uap_private *, int);
++int sbi_prog_helper(uap_private *);
++
++int sbi_wakeup_firmware(uap_private * priv);
++
++#endif /* _UAP_DRV_H */
+diff --git a/drivers/net/wireless/libertas_uap/uap_fw.h b/drivers/net/wireless/libertas_uap/uap_fw.h
+new file mode 100644
+index 0000000..23a40d6
+--- /dev/null
++++ b/drivers/net/wireless/libertas_uap/uap_fw.h
+@@ -0,0 +1,359 @@
++/** @file uap_fw.h
++ *
++ * @brief This file contains firmware specific defines.
++ *
++ * Copyright (C) 2008-2009, Marvell International Ltd.
++ *
++ * This software file (the "File") is distributed by Marvell International
++ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
++ * (the "License"). You may use, redistribute and/or modify this File in
++ * accordance with the terms and conditions of the License, a copy of which
++ * is available along with the File in the gpl.txt file or by writing to
++ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++ *
++ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
++ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
++ * this warranty disclaimer.
++ *
++ */
++/********************************************************
++Change log:
++ 02/26/08: Initial creation
++********************************************************/
++
++#ifndef _UAP_FW_H
++#define _UAP_FW_H
++
++/** uap upload size */
++#define UAP_UPLD_SIZE 2312
++/** Packet type Micro AP */
++#define PKT_TYPE_MICROAP 1
++/** Packet type client */
++#define PKT_TYPE_CLIENT 0
++
++/** TxPD descriptor */
++typedef struct _TxPD
++{
++ /** Bss Type */
++ u8 BssType;
++ /** Bss num */
++ u8 BssNum;
++ /** Tx packet length */
++ u16 TxPktLength;
++ /** Tx packet offset */
++ u16 TxPktOffset;
++ /** Tx packet type */
++ u16 TxPktType;
++ /** Tx Control */
++ u32 TxControl;
++ /** reserved */
++ u32 reserved[2];
++} __ATTRIB_PACK__ TxPD, *PTxPD;
++
++/** RxPD Descriptor */
++typedef struct _RxPD
++{
++ /** Bss Type */
++ u8 BssType;
++ /** Bss Num */
++ u8 BssNum;
++ /** Tx packet length */
++ u16 RxPktLength;
++ /** Tx packet offset */
++ u16 RxPktOffset;
++} __ATTRIB_PACK__ RxPD, *PRxPD;
++
++#ifdef BIG_ENDIAN
++/** Convert from 16 bit little endian format to CPU format */
++#define uap_le16_to_cpu(x) le16_to_cpu(x)
++/** Convert from 32 bit little endian format to CPU format */
++#define uap_le32_to_cpu(x) le32_to_cpu(x)
++/** Convert from 64 bit little endian format to CPU format */
++#define uap_le64_to_cpu(x) le64_to_cpu(x)
++/** Convert to 16 bit little endian format from CPU format */
++#define uap_cpu_to_le16(x) cpu_to_le16(x)
++/** Convert to 32 bit little endian format from CPU format */
++#define uap_cpu_to_le32(x) cpu_to_le32(x)
++/** Convert to 64 bit little endian format from CPU format */
++#define uap_cpu_to_le64(x) cpu_to_le64(x)
++
++/** Convert TxPD to little endian format from CPU format */
++#define endian_convert_TxPD(x); \
++ { \
++ (x)->TxPktLength = uap_cpu_to_le16((x)->TxPktLength); \
++ (x)->TxPktOffset = uap_cpu_to_le32((x)->TxPktOffset); \
++ (x)->TxControl = uap_cpu_to_le32((x)->TxControl); \
++ (x)->TxPktType = uap_cpu_to_le32((x)->TxPktType); \
++ }
++
++/** Convert RxPD from little endian format to CPU format */
++#define endian_convert_RxPD(x); \
++ { \
++ (x)->RxPktLength = uap_le16_to_cpu((x)->RxPktLength); \
++ (x)->RxPktOffset = uap_le32_to_cpu((x)->RxPktOffset); \
++ }
++#else /* BIG_ENDIAN */
++/** Do nothing */
++#define uap_le16_to_cpu(x) x
++/** Do nothing */
++#define uap_le32_to_cpu(x) x
++/** Do nothing */
++#define uap_le64_to_cpu(x) x
++/** Do nothing */
++#define uap_cpu_to_le16(x) x
++/** Do nothing */
++#define uap_cpu_to_le32(x) x
++/** Do nothing */
++#define uap_cpu_to_le64(x) x
++
++/** Do nothing */
++#define endian_convert_TxPD(x)
++/** Do nothing */
++#define endian_convert_RxPD(x)
++#endif /* BIG_ENDIAN */
++
++/** Host Command ID : Function initialization */
++#define HostCmd_CMD_FUNC_INIT 0x00a9
++/** Host Command ID : Function shutdown */
++#define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa
++
++/** Host Command id: SYS_INFO */
++#define HOST_CMD_APCMD_SYS_INFO 0x00ae
++/** Host Command id: SYS_RESET */
++#define HOST_CMD_APCMD_SYS_RESET 0x00af
++/** Host Command id: SYS_CONFIGURE */
++#define HOST_CMD_APCMD_SYS_CONFIGURE 0x00b0
++/** Host Command id: BSS_START */
++#define HOST_CMD_APCMD_BSS_START 0x00b1
++/** Host Command id: SYS_STOP */
++#define HOST_CMD_APCMD_BSS_STOP 0x00b2
++/** Host Command id: STA_LIST */
++#define HOST_CMD_APCMD_STA_LIST 0x00b3
++/** Host Command id: STA_FILTER_TABLE */
++#define HOST_CMD_APCMD_STA_FILTER_TABLE 0x00b4
++/** Host Command id: STA_DEAUTH */
++#define HOST_CMD_APCMD_STA_DEAUTH 0x00b5
++/** Host Command id: SOFT_RESET */
++#define HOST_CMD_APCMD_SOFT_RESET 0x00d5
++/** Host Command id: POWER_MGMT_EXT */
++#define HOST_CMD_POWER_MGMT_EXT 0x00ef
++/** Host Command id: SLEEP_CONFIRM*/
++#define HOST_CMD_SLEEP_CONFIRM 0x00d8
++
++/** TLV type : SSID */
++#define TLV_TYPE_SSID 0x0000
++/** TLV type : Rates */
++#define TLV_TYPE_RATES 0x0001
++/** TLV type : PHY DS */
++#define TLV_TYPE_PHY_DS 0x0003
++
++/** TLV Id : Base id */
++#define PROPRIETARY_TLV_BASE_ID 0x0100
++/** TLV Id : AP_MAC_ADDRESS */
++#define MRVL_AP_MAC_ADDRESS_TLV_ID (PROPRIETARY_TLV_BASE_ID + 43)
++/** TLV Id : Beacon period */
++#define MRVL_BEACON_PERIOD_TLV_ID (PROPRIETARY_TLV_BASE_ID + 44)
++/** TLV Id : Dtim period */
++#define MRVL_DTIM_PERIOD_TLV_ID (PROPRIETARY_TLV_BASE_ID + 45)
++/** TLV Id : Basic rates */
++#define MRVL_BASIC_RATES_TLV_ID (PROPRIETARY_TLV_BASE_ID + 46)
++/** TLV Id : Tx Power */
++#define MRVL_TX_POWER_TLV_ID (PROPRIETARY_TLV_BASE_ID + 47)
++/** TLV Id : Broadcast SSID control */
++#define MRVL_BCAST_SSID_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 48)
++/** TLV Id : Preamble control */
++#define MRVL_PREAMBLE_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 49)
++/** TLV Id : Antenna control */
++#define MRVL_ANTENNA_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 50)
++/** TLV Id : RTS threshold */
++#define MRVL_RTS_THRESHOLD_TLV_ID (PROPRIETARY_TLV_BASE_ID + 51)
++/** TLV Id : Radio control */
++#define MRVL_RADIO_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 52)
++/** TLV Id : TX data rate */
++#define MRVL_TX_DATA_RATE_TLV_ID (PROPRIETARY_TLV_BASE_ID + 53)
++/** TLV Id : Packet forward control */
++#define MRVL_PKT_FWD_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 54)
++/** TLV Id : STA info */
++#define MRVL_STA_INFO_TLV_ID (PROPRIETARY_TLV_BASE_ID + 55)
++/** TLV Id : STA MAC address filter */
++#define MRVL_STA_MAC_ADDR_FILTER_TLV_ID (PROPRIETARY_TLV_BASE_ID + 56)
++/** TLV Id : STA ageout timer */
++#define MRVL_STA_AGEOUT_TIMER_TLV_ID (PROPRIETARY_TLV_BASE_ID + 57)
++/** TLV Id : Security config */
++#define MRVL_SECURITY_CFG_TLV_ID (PROPRIETARY_TLV_BASE_ID + 58)
++/** TLV Id : WEP KEY */
++#define MRVL_WEP_KEY_TLV_ID (PROPRIETARY_TLV_BASE_ID + 59)
++/** TLV Id : WPA Passphrase */
++#define MRVL_WPA_PASSPHRASE_TLV_ID (PROPRIETARY_TLV_BASE_ID + 60)
++
++/** Action get */
++#define ACTION_GET 0
++/** Action set */
++#define ACTION_SET 1
++/** Length of ethernet address */
++#ifndef ETH_ALEN
++#define ETH_ALEN 6
++#endif
++
++/** HostCmd_DS_GEN */
++typedef struct
++{
++ /** Command */
++ u16 Command;
++ /** Size */
++ u16 Size;
++ /** Sequence number */
++ u16 SeqNum;
++ /** Result */
++ u16 Result;
++} __ATTRIB_PACK__ HostCmd_DS_GEN;
++
++/** Size of HostCmd_DS_GEN */
++#define S_DS_GEN sizeof(HostCmd_DS_GEN)
++
++/** _HostCmd_HEADER*/
++typedef struct
++{
++ /** Command Header : Command */
++ u16 Command;
++ /** Command Header : Size */
++ u16 Size;
++} __ATTRIB_PACK__ HostCmd_HEADER;
++
++/** HostCmd_SYS_CONFIG */
++typedef struct _HostCmd_SYS_CONFIG
++{
++ /** CMD Action GET/SET*/
++ u16 Action;
++ /** Tlv buffer */
++ u8 TlvBuffer[0];
++} __ATTRIB_PACK__ HostCmd_SYS_CONFIG;
++
++/** HostCmd_DS_POWER_MGMT_EXT */
++typedef struct _HostCmd_DS_POWER_MGMT_EXT
++{
++ /** CMD Action Get/Set*/
++ u16 action;
++ /** power mode */
++ u16 power_mode;
++} __ATTRIB_PACK__ HostCmd_DS_POWER_MGMT_EXT;
++
++/** _HostCmd_DS_COMMAND*/
++typedef struct _HostCmd_DS_COMMAND
++{
++
++ /** Command Header : Command */
++ u16 Command;
++ /** Command Header : Size */
++ u16 Size;
++ /** Command Header : Sequence number */
++ u16 SeqNum;
++ /** Command Header : Result */
++ u16 Result;
++ /** Command Body */
++ union
++ {
++ HostCmd_SYS_CONFIG sys_config;
++ HostCmd_DS_POWER_MGMT_EXT pm_cfg;
++
++ } params;
++} __ATTRIB_PACK__ HostCmd_DS_COMMAND;
++
++/** MrvlIEtypesHeader_*/
++typedef struct _MrvlIEtypesHeader
++{
++ /** Header type */
++ u16 Type;
++ /** Header length */
++ u16 Len;
++} __ATTRIB_PACK__ MrvlIEtypesHeader_t;
++
++/** MrvlIEtypes_Data_t */
++typedef struct _MrvlIEtypes_Data_t
++{
++ /** Header */
++ MrvlIEtypesHeader_t Header;
++ /** Data */
++ u8 Data[1];
++} __ATTRIB_PACK__ MrvlIEtypes_Data_t;
++
++/** MrvlIEtypes_ChanListParamSet_t */
++typedef struct _MrvlIEtypes_MacAddr_t
++{
++ /** Header */
++ MrvlIEtypesHeader_t Header;
++ /** AP MAC address */
++ u8 ApMacAddr[ETH_ALEN];
++} __ATTRIB_PACK__ MrvlIEtypes_MacAddr_t;
++
++/** Event ID: BSS started */
++#define MICRO_AP_EV_ID_BSS_START 46
++
++/** Event ID: BSS idle event */
++#define MICRO_AP_EV_BSS_IDLE 67
++
++/** Event ID: BSS active event */
++#define MICRO_AP_EV_BSS_ACTIVE 68
++
++/** Event ID: PS_AWAKE */
++#define EVENT_PS_AWAKE 0x0a
++
++/** Event ID: PS_SLEEP */
++#define EVENT_PS_SLEEP 0x0b
++
++/** PS_STATE */
++typedef enum _PS_STATE
++{
++ PS_STATE_AWAKE,
++ PS_STATE_PRE_SLEEP,
++ PS_STATE_SLEEP
++} PS_STATE;
++
++/** TLV type: AP Sleep param */
++#define TLV_TYPE_AP_SLEEP_PARAM (PROPRIETARY_TLV_BASE_ID + 106)
++/** TLV type: AP Inactivity Sleep param */
++#define TLV_TYPE_AP_INACT_SLEEP_PARAM (PROPRIETARY_TLV_BASE_ID + 107)
++
++/** MrvlIEtypes_sleep_param_t */
++typedef struct _MrvlIEtypes_sleep_param_t
++{
++ /** Header */
++ MrvlIEtypesHeader_t header;
++ /** control bitmap */
++ u32 ctrl_bitmap;
++ /** min_sleep */
++ u32 min_sleep;
++ /** max_sleep */
++ u32 max_sleep;
++} __ATTRIB_PACK__ MrvlIEtypes_sleep_param_t;
++
++/** MrvlIEtypes_inact_sleep_param_t */
++typedef struct _MrvlIEtypes_inact_sleep_param_t
++{
++ /** Header */
++ MrvlIEtypesHeader_t header;
++ /** inactivity timeout */
++ u32 inactivity_to;
++ /** min_awake */
++ u32 min_awake;
++ /** max_awake */
++ u32 max_awake;
++} __ATTRIB_PACK__ MrvlIEtypes_inact_sleep_param_t;
++
++/** AP_Event */
++typedef struct _AP_Event
++{
++ /** Event ID */
++ u32 EventId;
++ /*
++ * Reserved for STA_ASSOCIATED event and contains
++ * status information for the MIC_COUNTERMEASURES event.
++ */
++ /** Reserved/status */
++ u16 status;
++ /** AP MAC address */
++ u8 MacAddr[ETH_ALEN];
++} __ATTRIB_PACK__ AP_Event;
++#endif /* _UAP_FW_H */
+diff --git a/drivers/net/wireless/libertas_uap/uap_headers.h b/drivers/net/wireless/libertas_uap/uap_headers.h
+new file mode 100644
+index 0000000..fa09af4
+--- /dev/null
++++ b/drivers/net/wireless/libertas_uap/uap_headers.h
+@@ -0,0 +1,64 @@
++/** @file uap_headers.h
++ *
++ * @brief This file contains all the necessary include file.
++ *
++ * Copyright (C) 2008-2009, Marvell International Ltd.
++ *
++ * This software file (the "File") is distributed by Marvell International
++ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
++ * (the "License"). You may use, redistribute and/or modify this File in
++ * accordance with the terms and conditions of the License, a copy of which
++ * is available along with the File in the gpl.txt file or by writing to
++ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++ *
++ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
++ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
++ * this warranty disclaimer.
++ *
++ */
++#ifndef _UAP_HEADERS_H
++#define _UAP_HEADERS_H
++
++/* Linux header files */
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/version.h>
++#include <linux/param.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/proc_fs.h>
++#include <linux/kthread.h>
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
++#include <linux/semaphore.h>
++#else
++#include <asm/semaphore.h>
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
++#include <linux/config.h>
++#endif
++
++/* Net header files */
++#include <linux/netdevice.h>
++#include <linux/net.h>
++#include <linux/skbuff.h>
++#include <linux/if_ether.h>
++#include <linux/etherdevice.h>
++#include <net/sock.h>
++#include <linux/netlink.h>
++#include <linux/firmware.h>
++#include <linux/delay.h>
++
++#include "uap_drv.h"
++#include "uap_fw.h"
++
++#include <linux/mmc/sdio.h>
++#include <linux/mmc/sdio_ids.h>
++#include <linux/mmc/sdio_func.h>
++#include <linux/mmc/card.h>
++#include "uap_sdio_mmc.h"
++
++#endif /* _UAP_HEADERS_H */
+diff --git a/drivers/net/wireless/libertas_uap/uap_main.c b/drivers/net/wireless/libertas_uap/uap_main.c
+new file mode 100644
+index 0000000..6ad8403
+--- /dev/null
++++ b/drivers/net/wireless/libertas_uap/uap_main.c
+@@ -0,0 +1,1817 @@
++/** @file uap_main.c
++ * @brief This file contains the major functions in uAP
++ * driver. It includes init, exit etc..
++ * This file also contains the initialization for SW,
++ * FW and HW
++ *
++ * Copyright (C) 2008-2009, Marvell International Ltd.
++ *
++ * This software file (the "File") is distributed by Marvell International
++ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
++ * (the "License"). You may use, redistribute and/or modify this File in
++ * accordance with the terms and conditions of the License, a copy of which
++ * is available along with the File in the gpl.txt file or by writing to
++ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++ *
++ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
++ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
++ * this warranty disclaimer.
++ *
++ */
++/**
++ * @mainpage uAP Linux Driver
++ *
++ * @section overview_sec Overview
++ *
++ * This is Linux reference driver for Marvell uAP.
++ *
++ * @section copyright_sec Copyright
++ *
++ * Copyright (C) 2008, Marvell International Ltd.
++ *
++ */
++
++#include "uap_headers.h"
++
++/**
++ * the global variable of a pointer to uap_private
++ * structure variable
++ */
++uap_private *uappriv = NULL;
++#ifdef DEBUG_LEVEL1
++#define DEFAULT_DEBUG_MASK (DBG_MSG | DBG_FATAL | DBG_ERROR)
++u32 drvdbg = DEFAULT_DEBUG_MASK;
++#endif
++/** Helper name */
++char *helper_name = NULL;
++/** Firmware name */
++char *fw_name = NULL;
++
++/** Semaphore for add/remove card */
++SEMAPHORE AddRemoveCardSem;
++
++/********************************************************
++ Local Functions
++********************************************************/
++/**
++ * @brief This function send sleep confirm command to firmware
++ *
++ * @param priv A pointer to uap_private structure
++ * @return UAP_STATUS_SUCCESS for success otherwise UAP_STATUS_FAILURE
++ */
++static int
++uap_dnld_sleep_confirm_cmd(uap_private * priv)
++{
++ uap_adapter *Adapter = priv->adapter;
++ int ret = UAP_STATUS_SUCCESS;
++ ENTER();
++ PRINTM(CMND, "Sleep confirm\n");
++ Adapter->cmd_pending = TRUE;
++ Adapter->cmd_wait_option = HostCmd_OPTION_WAITFORRSP_SLEEPCONFIRM;
++ ret =
++ sbi_host_to_card(priv, (u8 *) & Adapter->PSConfirmSleep,
++ sizeof(PS_CMD_ConfirmSleep));
++ if (ret != UAP_STATUS_SUCCESS) {
++ Adapter->ps_state = PS_STATE_AWAKE;
++ Adapter->cmd_pending = FALSE;
++ Adapter->cmd_wait_option = FALSE;
++ }
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function process sleep confirm resp from firmware
++ *
++ * @param priv A pointer to uap_private structure
++ * @param resp A pointer to resp buf
++ * @param resp_len resp buf len
++ * @return UAP_STATUS_SUCCESS for success otherwise UAP_STATUS_FAILURE
++ */
++int
++uap_process_sleep_confirm_resp(uap_private * priv, u8 * resp, int resp_len)
++{
++ int ret = UAP_STATUS_SUCCESS;
++ HostCmd_DS_COMMAND *cmd;
++ uap_adapter *Adapter = priv->adapter;
++ ENTER();
++ PRINTM(CMND, "Sleep confirm resp\n");
++ if (!resp_len) {
++ PRINTM(ERROR, "Cmd Size is 0\n");
++ ret = -EFAULT;
++ goto done;
++ }
++ cmd = (HostCmd_DS_COMMAND *) resp;
++ cmd->Result = uap_le16_to_cpu(cmd->Result);
++ if (cmd->Result != UAP_STATUS_SUCCESS) {
++ PRINTM(ERROR, "HOST_CMD_APCMD_PS_SLEEP_CONFIRM fail=%x\n", cmd->Result);
++ ret = -EFAULT;
++ }
++ done:
++ if (ret == UAP_STATUS_SUCCESS)
++ Adapter->ps_state = PS_STATE_SLEEP;
++ else
++ Adapter->ps_state = PS_STATE_AWAKE;
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function checks condition and prepares to
++ * send sleep confirm command to firmware if OK.
++ *
++ * @param priv A pointer to uap_private structure
++ * @return n/a
++ */
++static void
++uap_ps_cond_check(uap_private * priv)
++{
++ uap_adapter *Adapter = priv->adapter;
++
++ ENTER();
++ if (!priv->uap_dev.cmd_sent &&
++ !Adapter->cmd_pending && !Adapter->IntCounter) {
++ uap_dnld_sleep_confirm_cmd(priv);
++ } else {
++ PRINTM(INFO, "Delay Sleep Confirm (%s%s%s)\n",
++ (priv->uap_dev.cmd_sent) ? "D" : "",
++ (Adapter->cmd_pending) ? "C" : "",
++ (Adapter->IntCounter) ? "I" : "");
++ }
++ LEAVE();
++}
++
++/**
++ * @brief This function add cmd to cmdQ and waiting for response
++ *
++ * @param priv A pointer to uap_private structure
++ * @param skb A pointer to the skb for process
++ * @param wait_option Wait option
++ * @return UAP_STATUS_SUCCESS for success otherwise UAP_STATUS_FAILURE
++ */
++static int
++uap_process_cmd(uap_private * priv, struct sk_buff *skb, u8 wait_option)
++{
++ uap_adapter *Adapter = priv->adapter;
++ int ret = UAP_STATUS_SUCCESS;
++ HostCmd_DS_COMMAND *cmd;
++ u8 *headptr;
++ ENTER();
++ if (Adapter->HardwareStatus != HWReady) {
++ PRINTM(ERROR, "Hw not ready, uap_process_cmd\n");
++ kfree(skb);
++ LEAVE();
++ return -EFAULT;
++ }
++ skb->cb[0] = wait_option;
++ headptr = skb->data;
++ *(u16 *) & headptr[0] = uap_cpu_to_le16(skb->len);
++ *(u16 *) & headptr[2] = uap_cpu_to_le16(MV_TYPE_CMD);
++ cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN);
++ Adapter->SeqNum++;
++ cmd->SeqNum = uap_cpu_to_le16(Adapter->SeqNum);
++ PRINTM(CMND, "process_cmd: %x\n", cmd->Command);
++ DBG_HEXDUMP(CMD_D, "process_cmd", (u8 *) cmd, cmd->Size);
++ if (!wait_option) {
++ skb_queue_tail(&priv->adapter->cmd_queue, skb);
++ wake_up_interruptible(&priv->MainThread.waitQ);
++ LEAVE();
++ return ret;
++ }
++ if (OS_ACQ_SEMAPHORE_BLOCK(&Adapter->CmdSem)) {
++ PRINTM(ERROR, "Acquire semaphore error, uap_prepare_cmd\n");
++ kfree(skb);
++ LEAVE();
++ return -EBUSY;
++ }
++ skb_queue_tail(&priv->adapter->cmd_queue, skb);
++ Adapter->CmdWaitQWoken = FALSE;
++ wake_up_interruptible(&priv->MainThread.waitQ);
++ /* Sleep until response is generated by FW */
++ if (wait_option == HostCmd_OPTION_WAITFORRSP_TIMEOUT) {
++ if (!os_wait_interruptible_timeout
++ (Adapter->cmdwait_q, Adapter->CmdWaitQWoken, MRVDRV_TIMER_20S)) {
++ PRINTM(ERROR, "Cmd timeout\n");
++ Adapter->cmd_pending = FALSE;
++ ret = -EFAULT;
++ }
++ } else
++ wait_event_interruptible(Adapter->cmdwait_q, Adapter->CmdWaitQWoken);
++ OS_REL_SEMAPHORE(&Adapter->CmdSem);
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief Inspect the response buffer for pointers to expected TLVs
++ *
++ *
++ * @param pTlv Pointer to the start of the TLV buffer to parse
++ * @param tlvBufSize Size of the TLV buffer
++ * @param reqTlvType request tlv's tlvtype
++ * @param ppTlv Output parameter: Pointer to the request TLV if found
++ *
++ * @return void
++ */
++static void
++uap_get_tlv_ptrs(MrvlIEtypes_Data_t * pTlv, int tlvBufSize,
++ u16 reqTlvType, MrvlIEtypes_Data_t ** ppTlv)
++{
++ MrvlIEtypes_Data_t *pCurrentTlv;
++ int tlvBufLeft;
++ u16 tlvType;
++ u16 tlvLen;
++
++ ENTER();
++ pCurrentTlv = pTlv;
++ tlvBufLeft = tlvBufSize;
++ *ppTlv = NULL;
++ PRINTM(INFO, "uap_get_tlv: tlvBufSize = %d, reqTlvType=%x\n", tlvBufSize,
++ reqTlvType);
++ while (tlvBufLeft >= sizeof(MrvlIEtypesHeader_t)) {
++ tlvType = uap_le16_to_cpu(pCurrentTlv->Header.Type);
++ tlvLen = uap_le16_to_cpu(pCurrentTlv->Header.Len);
++ if (reqTlvType == tlvType)
++ *ppTlv = (MrvlIEtypes_Data_t *) pCurrentTlv;
++ if (*ppTlv) {
++ HEXDUMP("TLV Buf", (u8 *) * ppTlv, tlvLen);
++ break;
++ }
++ tlvBufLeft -= (sizeof(pTlv->Header) + tlvLen);
++ pCurrentTlv = (MrvlIEtypes_Data_t *) (pCurrentTlv->Data + tlvLen);
++ } /* while */
++ LEAVE();
++}
++
++/**
++ * @brief This function get mac
++ *
++ * @param priv A pointer to uap_private structure
++ * @return UAP_STATUS_SUCCESS on success, otherwise failure code
++ */
++static int
++uap_get_mac_address(uap_private * priv)
++{
++ int ret = UAP_STATUS_SUCCESS;
++ u32 CmdSize;
++ HostCmd_DS_COMMAND *cmd;
++ uap_adapter *Adapter = priv->adapter;
++ struct sk_buff *skb;
++ MrvlIEtypes_MacAddr_t *pMacAddrTlv;
++ MrvlIEtypes_Data_t *pTlv;
++ u16 tlvBufSize;
++ ENTER();
++ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
++ if (!skb) {
++ PRINTM(ERROR, "No free skb\n");
++ ret = -ENOMEM;
++ goto done;
++ }
++ CmdSize =
++ S_DS_GEN + sizeof(HostCmd_SYS_CONFIG) + sizeof(MrvlIEtypes_MacAddr_t);
++ cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN);
++ cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE);
++ cmd->Size = uap_cpu_to_le16(CmdSize);
++ cmd->params.sys_config.Action = uap_cpu_to_le16(ACTION_GET);
++ pMacAddrTlv =
++ (MrvlIEtypes_MacAddr_t *) (skb->data + INTF_HEADER_LEN + S_DS_GEN +
++ sizeof(HostCmd_SYS_CONFIG));
++ pMacAddrTlv->Header.Type = uap_cpu_to_le16(MRVL_AP_MAC_ADDRESS_TLV_ID);
++ pMacAddrTlv->Header.Len = uap_cpu_to_le16(ETH_ALEN);
++ skb_put(skb, CmdSize + INTF_HEADER_LEN);
++ if (UAP_STATUS_SUCCESS !=
++ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) {
++ PRINTM(ERROR, "Fail to process cmd SYS_CONFIGURE Query\n");
++ ret = -EFAULT;
++ goto done;
++ }
++ if (!Adapter->CmdSize) {
++ PRINTM(ERROR, "Cmd Size is 0\n");
++ ret = -EFAULT;
++ goto done;
++ }
++ cmd = (HostCmd_DS_COMMAND *) Adapter->CmdBuf;
++ cmd->Result = uap_le16_to_cpu(cmd->Result);
++ if (cmd->Result != UAP_STATUS_SUCCESS) {
++ PRINTM(ERROR, "uap_get_mac_address fail=%x\n", cmd->Result);
++ ret = -EFAULT;
++ goto done;
++ }
++ pTlv =
++ (MrvlIEtypes_Data_t *) (Adapter->CmdBuf + S_DS_GEN +
++ sizeof(HostCmd_SYS_CONFIG));
++ tlvBufSize = Adapter->CmdSize - S_DS_GEN - sizeof(HostCmd_SYS_CONFIG);
++ uap_get_tlv_ptrs(pTlv, tlvBufSize, MRVL_AP_MAC_ADDRESS_TLV_ID,
++ (MrvlIEtypes_Data_t **) & pMacAddrTlv);
++ if (pMacAddrTlv) {
++ memcpy(priv->uap_dev.netdev->dev_addr, pMacAddrTlv->ApMacAddr,
++ ETH_ALEN);
++ HEXDUMP("Original MAC addr", priv->uap_dev.netdev->dev_addr, ETH_ALEN);
++ }
++ done:
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function checks the conditions and sends packet to device
++ *
++ * @param priv A pointer to uap_private structure
++ * @param skb A pointer to the skb for process
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++static int
++uap_process_tx(uap_private * priv, struct sk_buff *skb)
++{
++ uap_adapter *Adapter = priv->adapter;
++ int ret = UAP_STATUS_SUCCESS;
++ TxPD *pLocalTxPD;
++ u8 *headptr;
++ struct sk_buff *newskb;
++ int newheadlen;
++ ENTER();
++ ASSERT(skb);
++ if (!skb) {
++ LEAVE();
++ return UAP_STATUS_FAILURE;
++ }
++ if (skb_headroom(skb) < (sizeof(TxPD) + INTF_HEADER_LEN + HEADER_ALIGNMENT)) {
++ newheadlen = sizeof(TxPD) + INTF_HEADER_LEN + HEADER_ALIGNMENT;
++ PRINTM(WARN, "Tx: Insufficient skb headroom %d\n", skb_headroom(skb));
++ /* Insufficient skb headroom - allocate a new skb */
++ newskb = skb_realloc_headroom(skb, newheadlen);
++ if (unlikely(newskb == NULL)) {
++ PRINTM(ERROR, "Tx: Cannot allocate skb\n");
++ ret = UAP_STATUS_FAILURE;
++ goto done;
++ }
++ kfree_skb(skb);
++ skb = newskb;
++ PRINTM(INFO, "new skb headroom %d\n", skb_headroom(skb));
++ }
++ /* headptr should be aligned */
++ headptr = skb->data - sizeof(TxPD) - INTF_HEADER_LEN;
++ headptr = (u8 *) ((u32) headptr & ~((u32) (HEADER_ALIGNMENT - 1)));
++
++ pLocalTxPD = (TxPD *) (headptr + INTF_HEADER_LEN);
++ memset(pLocalTxPD, 0, sizeof(TxPD));
++ pLocalTxPD->BssType = PKT_TYPE_MICROAP;
++ pLocalTxPD->TxPktLength = skb->len;
++ /* offset of actual data */
++ pLocalTxPD->TxPktOffset = (long) skb->data - (long) pLocalTxPD;
++ endian_convert_TxPD(pLocalTxPD);
++ *(u16 *) & headptr[0] =
++ uap_cpu_to_le16(skb->len + ((long) skb->data - (long) headptr));
++ *(u16 *) & headptr[2] = uap_cpu_to_le16(MV_TYPE_DAT);
++ ret =
++ sbi_host_to_card(priv, headptr,
++ skb->len + ((long) skb->data - (long) headptr));
++ if (ret) {
++ PRINTM(ERROR, "uap_process_tx Error: sbi_host_to_card failed: 0x%X\n",
++ ret);
++ Adapter->dbg.num_tx_host_to_card_failure++;
++ goto done;
++ }
++ PRINTM(DATA, "Data => FW\n");
++ DBG_HEXDUMP(DAT_D, "Tx", headptr,
++ MIN(skb->len + sizeof(TxPD), DATA_DUMP_LEN));
++ done:
++ /* Freed skb */
++ kfree_skb(skb);
++ LEAVE();
++ return ret;
++}
++
++static struct netlink_kernel_cfg cfg = {
++ .groups = NL_MULTICAST_GROUP,
++};
++
++/**
++ * @brief This function initializes the adapter structure
++ * and set default value to the member of adapter.
++ *
++ * @param priv A pointer to uap_private structure
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++static int
++uap_init_sw(uap_private * priv)
++{
++ uap_adapter *Adapter = priv->adapter;
++
++ ENTER();
++
++ if (!(Adapter->CmdBuf = kmalloc(MRVDRV_SIZE_OF_CMD_BUFFER, GFP_KERNEL))) {
++ PRINTM(INFO, "Failed to allocate command buffer!\n");
++ LEAVE();
++ return UAP_STATUS_FAILURE;
++ }
++
++ Adapter->cmd_pending = FALSE;
++ Adapter->CmdWaitQWoken = FALSE;
++ Adapter->ps_state = PS_STATE_AWAKE;
++ Adapter->WakeupTries = 0;
++
++ memset(&Adapter->PSConfirmSleep, 0, sizeof(PS_CMD_ConfirmSleep));
++ /** SDIO header */
++ Adapter->PSConfirmSleep.SDLen =
++ uap_cpu_to_le16(sizeof(PS_CMD_ConfirmSleep));
++ Adapter->PSConfirmSleep.SDType = uap_cpu_to_le16(MV_TYPE_CMD);
++ Adapter->PSConfirmSleep.SeqNum = 0;
++ Adapter->PSConfirmSleep.Command = uap_cpu_to_le16(HOST_CMD_SLEEP_CONFIRM);
++ Adapter->PSConfirmSleep.Size = uap_cpu_to_le16(sizeof(HostCmd_DS_GEN));
++ Adapter->PSConfirmSleep.Result = 0;
++
++ init_waitqueue_head(&Adapter->cmdwait_q);
++ OS_INIT_SEMAPHORE(&Adapter->CmdSem);
++
++ skb_queue_head_init(&Adapter->tx_queue);
++ skb_queue_head_init(&Adapter->cmd_queue);
++
++ /* Status variable */
++ Adapter->HardwareStatus = HWInitializing;
++
++ /* PnP support */
++ Adapter->SurpriseRemoved = FALSE;
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
++ Adapter->nl_sk = netlink_kernel_create(NETLINK_MARVELL,
++ NL_MULTICAST_GROUP, NULL,
++ THIS_MODULE);
++#else
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
++ Adapter->nl_sk = netlink_kernel_create(NETLINK_MARVELL,
++ NL_MULTICAST_GROUP, NULL, NULL,
++ THIS_MODULE);
++#else
++ Adapter->nl_sk = netlink_kernel_create(&init_net, NETLINK_MARVELL, &cfg);
++#endif
++#endif
++ if (!Adapter->nl_sk) {
++ PRINTM(ERROR,
++ "Could not initialize netlink event passing mechanism!\n");
++ }
++ LEAVE();
++ return UAP_STATUS_SUCCESS;
++}
++
++/**
++ * @brief This function sends FUNC_INIT command to firmware
++ *
++ * @param priv A pointer to uap_private structure
++ * @return UAP_STATUS_SUCCESS on success, otherwise failure code
++ */
++static int
++uap_func_init(uap_private * priv)
++{
++ int ret = UAP_STATUS_SUCCESS;
++ u32 CmdSize;
++ HostCmd_DS_GEN *cmd;
++ uap_adapter *Adapter = priv->adapter;
++ struct sk_buff *skb;
++ ENTER();
++ if (Adapter->HardwareStatus != HWReady) {
++ PRINTM(ERROR, "uap_func_init:Hardware is not ready!\n");
++ ret = -EFAULT;
++ goto done;
++ }
++ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
++ if (!skb) {
++ PRINTM(ERROR, "No free skb\n");
++ ret = -ENOMEM;
++ goto done;
++ }
++ CmdSize = sizeof(HostCmd_DS_GEN);
++ cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN);
++ cmd->Command = uap_cpu_to_le16(HostCmd_CMD_FUNC_INIT);
++ cmd->Size = uap_cpu_to_le16(CmdSize);
++ skb_put(skb, CmdSize + INTF_HEADER_LEN);
++ PRINTM(CMND, "HostCmd_CMD_FUNC_INIT\n");
++ if (UAP_STATUS_SUCCESS !=
++ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) {
++ PRINTM(ERROR, "Fail to process cmd HostCmd_CMD_FUNC_INIT\n");
++ ret = -EFAULT;
++ goto done;
++ }
++ done:
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function sends FUNC_SHUTDOWN command to firmware
++ *
++ * @param priv A pointer to uap_private structure
++ * @return UAP_STATUS_SUCCESS on success, otherwise failure code
++ */
++static int __exit
++uap_func_shutdown(uap_private * priv)
++{
++ int ret = UAP_STATUS_SUCCESS;
++ u32 CmdSize;
++ HostCmd_DS_GEN *cmd;
++ uap_adapter *Adapter = priv->adapter;
++ struct sk_buff *skb;
++ ENTER();
++ if (Adapter->HardwareStatus != HWReady) {
++ PRINTM(ERROR, "uap_func_shutdown:Hardware is not ready!\n");
++ ret = -EFAULT;
++ goto done;
++ }
++ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
++ if (!skb) {
++ PRINTM(ERROR, "No free skb\n");
++ ret = -ENOMEM;
++ goto done;
++ }
++ CmdSize = sizeof(HostCmd_DS_GEN);
++ cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN);
++ cmd->Command = uap_cpu_to_le16(HostCmd_CMD_FUNC_SHUTDOWN);
++ cmd->Size = uap_cpu_to_le16(CmdSize);
++ skb_put(skb, CmdSize + INTF_HEADER_LEN);
++ PRINTM(CMND, "HostCmd_CMD_FUNC_SHUTDOWN\n");
++ if (UAP_STATUS_SUCCESS !=
++ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) {
++ PRINTM(ERROR, "Fail to process cmd HostCmd_CMD_FUNC_SHUTDOWN\n");
++ ret = -EFAULT;
++ goto done;
++ }
++ done:
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function initializes firmware
++ *
++ * @param priv A pointer to uap_private structure
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++static int
++uap_init_fw(uap_private * priv)
++{
++ int ret = UAP_STATUS_SUCCESS;
++ ENTER();
++ sbi_disable_host_int(priv);
++ /* Check if firmware is already running */
++ if (sbi_check_fw_status(priv, 1) == UAP_STATUS_SUCCESS) {
++ PRINTM(MSG, "UAP FW already running! Skip FW download\n");
++ } else {
++ if ((ret = request_firmware(&priv->fw_helper, helper_name,
++ priv->hotplug_device)) < 0) {
++ PRINTM(FATAL,
++ "request_firmware() failed (helper), error code = %#x\n",
++ ret);
++ goto done;
++ }
++
++ /* Download the helper */
++ ret = sbi_prog_helper(priv);
++
++ if (ret) {
++ PRINTM(FATAL,
++ "Bootloader in invalid state! Helper download failed!\n");
++ ret = UAP_STATUS_FAILURE;
++ goto done;
++ }
++ if ((ret = request_firmware(&priv->firmware, fw_name,
++ priv->hotplug_device)) < 0) {
++ PRINTM(FATAL, "request_firmware() failed, error code = %#x\n", ret);
++ goto done;
++ }
++
++ /* Download the main firmware via the helper firmware */
++ if (sbi_prog_fw_w_helper(priv)) {
++ PRINTM(FATAL, "UAP FW download failed!\n");
++ ret = UAP_STATUS_FAILURE;
++ goto done;
++ }
++ /* Check if the firmware is downloaded successfully or not */
++ if (sbi_check_fw_status(priv, MAX_FIRMWARE_POLL_TRIES) ==
++ UAP_STATUS_FAILURE) {
++ PRINTM(FATAL, "FW failed to be active in time!\n");
++ ret = UAP_STATUS_FAILURE;
++ goto done;
++ }
++ PRINTM(MSG, "UAP FW is active\n");
++ }
++ sbi_enable_host_int(priv);
++ priv->adapter->HardwareStatus = HWReady;
++ if (uap_func_init(priv) != UAP_STATUS_SUCCESS) {
++ ret = UAP_STATUS_FAILURE;
++ goto done;
++ }
++ done:
++ if (priv->fw_helper)
++ release_firmware(priv->fw_helper);
++ if (priv->firmware)
++ release_firmware(priv->firmware);
++ LEAVE();
++ return ret;
++
++}
++
++/**
++ * @brief This function frees the structure of adapter
++ *
++ * @param priv A pointer to uap_private structure
++ * @return n/a
++ */
++static void
++uap_free_adapter(uap_private * priv)
++{
++ uap_adapter *Adapter = priv->adapter;
++
++ ENTER();
++
++ if (Adapter) {
++ if ((Adapter->nl_sk) && ((Adapter->nl_sk)->sk_socket)) {
++ sock_release((Adapter->nl_sk)->sk_socket);
++ Adapter->nl_sk = NULL;
++ }
++ if (Adapter->CmdBuf)
++ kfree(Adapter->CmdBuf);
++ skb_queue_purge(&priv->adapter->tx_queue);
++ skb_queue_purge(&priv->adapter->cmd_queue);
++ /* Free the adapter object itself */
++ kfree(Adapter);
++ priv->adapter = NULL;
++ }
++
++ LEAVE();
++}
++
++/**
++ * @brief This function handles the major job in uap driver.
++ * it handles the event generated by firmware, rx data received
++ * from firmware and tx data sent from kernel.
++ *
++ * @param data A pointer to uap_thread structure
++ * @return BT_STATUS_SUCCESS
++ */
++static int
++uap_service_main_thread(void *data)
++{
++ uap_thread *thread = data;
++ uap_private *priv = thread->priv;
++ uap_adapter *Adapter = priv->adapter;
++ wait_queue_t wait;
++ u8 ireg = 0;
++ struct sk_buff *skb;
++ ENTER();
++ uap_activate_thread(thread);
++ init_waitqueue_entry(&wait, current);
++ current->flags |= PF_NOFREEZE;
++
++ for (;;) {
++ add_wait_queue(&thread->waitQ, &wait);
++ OS_SET_THREAD_STATE(TASK_INTERRUPTIBLE);
++ if ((Adapter->WakeupTries) ||
++ (!Adapter->IntCounter && Adapter->ps_state == PS_STATE_PRE_SLEEP) ||
++ (!priv->adapter->IntCounter
++ && (priv->uap_dev.data_sent ||
++ skb_queue_empty(&priv->adapter->tx_queue))
++ && (priv->uap_dev.cmd_sent || Adapter->cmd_pending ||
++ skb_queue_empty(&priv->adapter->cmd_queue))
++ )) {
++ PRINTM(INFO, "Main: Thread sleeping...\n");
++ schedule();
++ }
++ OS_SET_THREAD_STATE(TASK_RUNNING);
++ remove_wait_queue(&thread->waitQ, &wait);
++ if (kthread_should_stop() || Adapter->SurpriseRemoved) {
++ PRINTM(INFO, "main-thread: break from main thread: "
++ "SurpriseRemoved=0x%x\n", Adapter->SurpriseRemoved);
++ /* Cancel pending command */
++ if (Adapter->cmd_pending == TRUE) {
++ /* Wake up cmd Q */
++ Adapter->CmdWaitQWoken = TRUE;
++ wake_up_interruptible(&Adapter->cmdwait_q);
++ }
++ break;
++ }
++
++ PRINTM(INFO, "Main: Thread waking up...\n");
++ if (priv->adapter->IntCounter) {
++ OS_INT_DISABLE;
++ Adapter->IntCounter = 0;
++ OS_INT_RESTORE;
++ sbi_get_int_status(priv, &ireg);
++ } else if ((priv->adapter->ps_state == PS_STATE_SLEEP) &&
++ (!skb_queue_empty(&priv->adapter->cmd_queue) ||
++ !skb_queue_empty(&priv->adapter->tx_queue))) {
++ priv->adapter->WakeupTries++;
++ PRINTM(CMND, "%lu : Wakeup device...\n", os_time_get());
++ sbi_wakeup_firmware(priv);
++ continue;
++ }
++ if (Adapter->ps_state == PS_STATE_PRE_SLEEP)
++ uap_ps_cond_check(priv);
++
++ /* The PS state is changed during processing of Sleep Request event
++ above */
++ if ((Adapter->ps_state == PS_STATE_SLEEP) ||
++ (Adapter->ps_state == PS_STATE_PRE_SLEEP))
++ continue;
++ /* Execute the next command */
++ if (!priv->uap_dev.cmd_sent && !Adapter->cmd_pending &&
++ (Adapter->HardwareStatus == HWReady)) {
++ if (!skb_queue_empty(&priv->adapter->cmd_queue)) {
++ skb = skb_dequeue(&priv->adapter->cmd_queue);
++ if (skb) {
++ Adapter->CmdSize = 0;
++ Adapter->cmd_pending = TRUE;
++ Adapter->cmd_wait_option = skb->cb[0];
++ if (sbi_host_to_card(priv, skb->data, skb->len)) {
++ PRINTM(ERROR, "Cmd:sbi_host_to_card failed!\n");
++ Adapter->cmd_pending = FALSE;
++ Adapter->dbg.num_cmd_host_to_card_failure++;
++ /* Wake up cmd Q */
++ Adapter->CmdWaitQWoken = TRUE;
++ wake_up_interruptible(&Adapter->cmdwait_q);
++ } else {
++ if (Adapter->cmd_wait_option ==
++ HostCmd_OPTION_WAITFORSEND) {
++ /* Wake up cmd Q */
++ Adapter->CmdWaitQWoken = TRUE;
++ wake_up_interruptible(&Adapter->cmdwait_q);
++ Adapter->cmd_wait_option = FALSE;
++ }
++ }
++ kfree_skb(skb);
++ }
++ }
++ }
++ if (!priv->uap_dev.data_sent && (Adapter->HardwareStatus == HWReady)) {
++ if (!skb_queue_empty(&priv->adapter->tx_queue)) {
++ skb = skb_dequeue(&priv->adapter->tx_queue);
++ if (skb) {
++ if (uap_process_tx(priv, skb)) {
++ priv->stats.tx_dropped++;
++ priv->stats.tx_errors++;
++ os_start_queue(priv);
++ } else {
++ priv->stats.tx_packets++;
++ priv->stats.tx_bytes += skb->len;
++ }
++
++ }
++ }
++ }
++ }
++ uap_deactivate_thread(thread);
++ LEAVE();
++ return UAP_STATUS_SUCCESS;
++}
++
++/**
++ * @brief uap hostcmd ioctl handler
++ *
++ * @param dev A pointer to net_device structure
++ * @param req A pointer to ifreq structure
++ * @return UAP_STATUS_SUCCESS --success, otherwise fail
++ */
++/********* format of ifr_data *************/
++/* buf_len + Hostcmd_body */
++/* buf_len: 4 bytes */
++/* the length of the buf which */
++/* can be used to return data */
++/* to application */
++/* Hostcmd_body */
++/*******************************************/
++static int
++uap_hostcmd_ioctl(struct net_device *dev, struct ifreq *req)
++{
++ u32 buf_len;
++ HostCmd_HEADER head;
++ uap_private *priv = (uap_private *) netdev_priv(dev);
++ uap_adapter *Adapter = priv->adapter;
++ int ret = UAP_STATUS_SUCCESS;
++ struct sk_buff *skb;
++
++ ENTER();
++
++ /* Sanity check */
++ if (req->ifr_data == NULL) {
++ PRINTM(ERROR, "uap_hostcmd_ioctl() corrupt data\n");
++ LEAVE();
++ return -EFAULT;
++ }
++ if (copy_from_user(&buf_len, req->ifr_data, sizeof(buf_len))) {
++ PRINTM(ERROR, "Copy from user failed\n");
++ LEAVE();
++ return -EFAULT;
++ }
++ memset(&head, 0, sizeof(HostCmd_HEADER));
++ /* Get the command size from user space */
++ if (copy_from_user
++ (&head, req->ifr_data + sizeof(buf_len), sizeof(HostCmd_HEADER))) {
++ PRINTM(ERROR, "Copy from user failed\n");
++ LEAVE();
++ return -EFAULT;
++ }
++ head.Size = uap_le16_to_cpu(head.Size);
++ if (head.Size > MRVDRV_SIZE_OF_CMD_BUFFER) {
++ PRINTM(ERROR, "CmdSize too big=%d\n", head.Size);
++ LEAVE();
++ return -EFAULT;
++ }
++ PRINTM(CMND, "ioctl: hostcmd=%x, size=%d,buf_len=%d\n", head.Command,
++ head.Size, buf_len);
++ skb = dev_alloc_skb(head.Size + INTF_HEADER_LEN);
++ if (!skb) {
++ PRINTM(ERROR, "No free skb\n");
++ LEAVE();
++ return -ENOMEM;
++ }
++
++ /* Get the command from user space */
++ if (copy_from_user
++ (skb->data + INTF_HEADER_LEN, req->ifr_data + sizeof(buf_len),
++ head.Size)) {
++ PRINTM(ERROR, "Copy from user failed\n");
++ LEAVE();
++ return -EFAULT;
++ }
++ skb_put(skb, head.Size + INTF_HEADER_LEN);
++ if (UAP_STATUS_SUCCESS !=
++ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP)) {
++ PRINTM(ERROR, "Fail to process cmd\n");
++ LEAVE();
++ return -EFAULT;
++ }
++ if (!Adapter->CmdSize) {
++ PRINTM(ERROR, "Cmd Size is 0\n");
++ LEAVE();
++ return -EFAULT;
++ }
++ if (Adapter->CmdSize > buf_len) {
++ PRINTM(ERROR, "buf_len is too small\n");
++ LEAVE();
++ return -EFAULT;
++ }
++ /* Copy to user */
++ if (copy_to_user
++ (req->ifr_data + sizeof(buf_len), Adapter->CmdBuf, Adapter->CmdSize)) {
++ PRINTM(ERROR, "Copy to user failed!\n");
++ LEAVE();
++ return -EFAULT;
++ }
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief uap power mode ioctl handler
++ *
++ * @param dev A pointer to net_device structure
++ * @param req A pointer to ifreq structure
++ * @return UAP_STATUS_SUCCESS --success, otherwise fail
++ */
++static int
++uap_power_mode_ioctl(struct net_device *dev, struct ifreq *req)
++{
++ ps_mgmt pm_cfg;
++ int ret = UAP_STATUS_SUCCESS;
++ uap_private *priv = (uap_private *) netdev_priv(dev);
++ uap_adapter *Adapter = priv->adapter;
++ struct sk_buff *skb = NULL;
++ HostCmd_DS_COMMAND *cmd;
++ u32 CmdSize;
++ u8 *tlv = NULL;
++ MrvlIEtypes_sleep_param_t *sleep_tlv = NULL;
++ MrvlIEtypes_inact_sleep_param_t *inact_tlv = NULL;
++ u16 tlv_buf_left = 0;
++ MrvlIEtypesHeader_t *tlvbuf = NULL;
++ u16 tlv_type = 0;
++ u16 tlv_len = 0;
++
++ ENTER();
++
++ /* Sanity check */
++ if (req->ifr_data == NULL) {
++ PRINTM(ERROR, "uap_power_mode_ioctl() corrupt data\n");
++ LEAVE();
++ return -EFAULT;
++ }
++
++ memset(&pm_cfg, 0, sizeof(ps_mgmt));
++ if (copy_from_user(&pm_cfg, req->ifr_data, sizeof(ps_mgmt))) {
++ PRINTM(ERROR, "Copy from user failed\n");
++ LEAVE();
++ return -EFAULT;
++ }
++ PRINTM(CMND,
++ "ioctl power: flag=0x%x ps_mode=%d ctrl_bitmap=%d min_sleep=%d max_sleep=%d "
++ "inact_to=%d min_awake=%d max_awake=%d\n", pm_cfg.flags,
++ (int) pm_cfg.ps_mode, (int) pm_cfg.sleep_param.ctrl_bitmap,
++ (int) pm_cfg.sleep_param.min_sleep,
++ (int) pm_cfg.sleep_param.max_sleep,
++ (int) pm_cfg.inact_param.inactivity_to,
++ (int) pm_cfg.inact_param.min_awake,
++ (int) pm_cfg.inact_param.max_awake);
++
++ if (pm_cfg.
++ flags & ~(PS_FLAG_PS_MODE | PS_FLAG_SLEEP_PARAM |
++ PS_FLAG_INACT_SLEEP_PARAM)) {
++ PRINTM(ERROR, "Invalid parameter: flags = 0x%x\n", pm_cfg.flags);
++ ret = -EINVAL;
++ goto done;
++ }
++ if (pm_cfg.ps_mode > PS_MODE_INACTIVITY) {
++ PRINTM(ERROR, "Invalid parameter: ps_mode = %d\n", (int) pm_cfg.flags);
++ ret = -EINVAL;
++ goto done;
++ }
++
++ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
++ if (!skb) {
++ PRINTM(INFO, "No free skb\n");
++ ret = -ENOMEM;
++ goto done;
++ }
++
++ CmdSize = S_DS_GEN + sizeof(HostCmd_DS_POWER_MGMT_EXT);
++
++ cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN);
++ cmd->Command = uap_cpu_to_le16(HOST_CMD_POWER_MGMT_EXT);
++ if (!pm_cfg.flags) {
++ cmd->params.pm_cfg.action = uap_cpu_to_le16(ACTION_GET);
++ } else {
++ cmd->params.pm_cfg.action = uap_cpu_to_le16(ACTION_SET);
++ cmd->params.pm_cfg.power_mode = uap_cpu_to_le16(pm_cfg.ps_mode);
++ tlv = (u8 *) & cmd->params.pm_cfg + sizeof(HostCmd_DS_POWER_MGMT_EXT);
++
++ if ((pm_cfg.ps_mode) && (pm_cfg.flags & PS_FLAG_SLEEP_PARAM)) {
++ sleep_tlv = (MrvlIEtypes_sleep_param_t *) tlv;
++ sleep_tlv->header.Type = uap_cpu_to_le16(TLV_TYPE_AP_SLEEP_PARAM);
++ sleep_tlv->header.Len =
++ uap_cpu_to_le16(sizeof(MrvlIEtypes_sleep_param_t) -
++ sizeof(MrvlIEtypesHeader_t));
++ sleep_tlv->ctrl_bitmap =
++ uap_cpu_to_le32(pm_cfg.sleep_param.ctrl_bitmap);
++ sleep_tlv->min_sleep =
++ uap_cpu_to_le32(pm_cfg.sleep_param.min_sleep);
++ sleep_tlv->max_sleep =
++ uap_cpu_to_le32(pm_cfg.sleep_param.max_sleep);
++ CmdSize += sizeof(MrvlIEtypes_sleep_param_t);
++ tlv += sizeof(MrvlIEtypes_sleep_param_t);
++ }
++ if ((pm_cfg.ps_mode == PS_MODE_INACTIVITY) &&
++ (pm_cfg.flags & PS_FLAG_INACT_SLEEP_PARAM)) {
++ inact_tlv = (MrvlIEtypes_inact_sleep_param_t *) tlv;
++ inact_tlv->header.Type =
++ uap_cpu_to_le16(TLV_TYPE_AP_INACT_SLEEP_PARAM);
++ inact_tlv->header.Len =
++ uap_cpu_to_le16(sizeof(MrvlIEtypes_inact_sleep_param_t) -
++ sizeof(MrvlIEtypesHeader_t));
++ inact_tlv->inactivity_to =
++ uap_cpu_to_le32(pm_cfg.inact_param.inactivity_to);
++ inact_tlv->min_awake =
++ uap_cpu_to_le32(pm_cfg.inact_param.min_awake);
++ inact_tlv->max_awake =
++ uap_cpu_to_le32(pm_cfg.inact_param.max_awake);
++ CmdSize += sizeof(MrvlIEtypes_inact_sleep_param_t);
++ tlv += sizeof(MrvlIEtypes_inact_sleep_param_t);
++ }
++ }
++ cmd->Size = uap_cpu_to_le16(CmdSize);
++ skb_put(skb, CmdSize + INTF_HEADER_LEN);
++ if (UAP_STATUS_SUCCESS !=
++ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP)) {
++ PRINTM(ERROR, "Fail to process cmd POWER_MODE\n");
++ ret = -EFAULT;
++ goto done;
++ }
++ if (!Adapter->CmdSize) {
++ PRINTM(ERROR, "Cmd Size is 0\n");
++ ret = -EFAULT;
++ goto done;
++ }
++ cmd = (HostCmd_DS_COMMAND *) Adapter->CmdBuf;
++ cmd->Result = uap_le16_to_cpu(cmd->Result);
++ if (cmd->Result != UAP_STATUS_SUCCESS) {
++ PRINTM(ERROR, "HOST_CMD_APCMD_POWER_MODE fail=%x\n", cmd->Result);
++ ret = -EFAULT;
++ goto done;
++ }
++ if (pm_cfg.flags) {
++ Adapter->psmode = uap_le16_to_cpu(cmd->params.pm_cfg.power_mode);
++ } else {
++ pm_cfg.flags = PS_FLAG_PS_MODE;
++ pm_cfg.ps_mode = uap_le16_to_cpu(cmd->params.pm_cfg.power_mode);
++ tlv_buf_left =
++ cmd->Size - (sizeof(HostCmd_DS_POWER_MGMT_EXT) + S_DS_GEN);
++ tlvbuf =
++ (MrvlIEtypesHeader_t *) ((u8 *) & cmd->params.pm_cfg +
++ sizeof(HostCmd_DS_POWER_MGMT_EXT));
++ while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
++ tlv_type = uap_le16_to_cpu(tlvbuf->Type);
++ tlv_len = uap_le16_to_cpu(tlvbuf->Len);
++ switch (tlv_type) {
++ case TLV_TYPE_AP_SLEEP_PARAM:
++ sleep_tlv = (MrvlIEtypes_sleep_param_t *) tlvbuf;
++ pm_cfg.flags |= PS_FLAG_SLEEP_PARAM;
++ pm_cfg.sleep_param.ctrl_bitmap =
++ uap_le32_to_cpu(sleep_tlv->ctrl_bitmap);
++ pm_cfg.sleep_param.min_sleep =
++ uap_le32_to_cpu(sleep_tlv->min_sleep);
++ pm_cfg.sleep_param.max_sleep =
++ uap_le32_to_cpu(sleep_tlv->max_sleep);
++ break;
++ case TLV_TYPE_AP_INACT_SLEEP_PARAM:
++ inact_tlv = (MrvlIEtypes_inact_sleep_param_t *) tlvbuf;
++ pm_cfg.flags |= PS_FLAG_INACT_SLEEP_PARAM;
++ pm_cfg.inact_param.inactivity_to =
++ uap_le32_to_cpu(inact_tlv->inactivity_to);
++ pm_cfg.inact_param.min_awake =
++ uap_le32_to_cpu(inact_tlv->min_awake);
++ pm_cfg.inact_param.max_awake =
++ uap_le32_to_cpu(inact_tlv->max_awake);
++ break;
++ }
++ tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t);
++ tlvbuf =
++ (MrvlIEtypesHeader_t *) ((u8 *) tlvbuf + tlv_len +
++ sizeof(MrvlIEtypesHeader_t));
++ }
++ /* Copy to user */
++ if (copy_to_user(req->ifr_data, &pm_cfg, sizeof(ps_mgmt))) {
++ PRINTM(ERROR, "Copy to user failed!\n");
++ LEAVE();
++ return -EFAULT;
++ }
++ }
++ done:
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function send bss_stop command to firmware
++ *
++ * @param priv A pointer to uap_private structure
++ * @return UAP_STATUS_SUCCESS on success, otherwise failure code
++ */
++static int
++uap_bss_stop(uap_private * priv)
++{
++ int ret = UAP_STATUS_SUCCESS;
++ u32 CmdSize;
++ HostCmd_DS_GEN *cmd;
++ uap_adapter *Adapter = priv->adapter;
++ struct sk_buff *skb;
++ ENTER();
++ if (Adapter->HardwareStatus != HWReady) {
++ PRINTM(ERROR, "uap_bss_stop:Hardware is not ready!\n");
++ ret = -EFAULT;
++ goto done;
++ }
++ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
++ if (!skb) {
++ PRINTM(ERROR, "No free skb\n");
++ ret = -ENOMEM;
++ goto done;
++ }
++ CmdSize = sizeof(HostCmd_DS_GEN);
++ cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN);
++ cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_BSS_STOP);
++ cmd->Size = uap_cpu_to_le16(CmdSize);
++ skb_put(skb, CmdSize + INTF_HEADER_LEN);
++ PRINTM(CMND, "APCMD_BSS_STOP\n");
++ if (UAP_STATUS_SUCCESS !=
++ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) {
++ PRINTM(ERROR, "Fail to process cmd BSS_STOP\n");
++ ret = -EFAULT;
++ goto done;
++ }
++ done:
++ LEAVE();
++ return ret;
++}
++
++/********************************************************
++ Global Functions
++********************************************************/
++/**
++ * @brief This function send soft_reset command to firmware
++ *
++ * @param priv A pointer to uap_private structure
++ * @return UAP_STATUS_SUCCESS on success, otherwise failure code
++ */
++int
++uap_soft_reset(uap_private * priv)
++{
++ int ret = UAP_STATUS_SUCCESS;
++ u32 CmdSize;
++ HostCmd_DS_GEN *cmd;
++ uap_adapter *Adapter = priv->adapter;
++ struct sk_buff *skb;
++ ENTER();
++ ret = uap_bss_stop(priv);
++ if (ret != UAP_STATUS_SUCCESS)
++ goto done;
++ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
++ if (!skb) {
++ PRINTM(ERROR, "No free skb\n");
++ ret = -ENOMEM;
++ goto done;
++ }
++ CmdSize = sizeof(HostCmd_DS_GEN);
++ cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN);
++ cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_SOFT_RESET);
++ cmd->Size = uap_cpu_to_le16(CmdSize);
++ skb_put(skb, CmdSize + INTF_HEADER_LEN);
++ PRINTM(CMND, "APCMD_SOFT_RESET\n");
++ if (UAP_STATUS_SUCCESS !=
++ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORSEND)) {
++ PRINTM(ERROR, "Fail to process cmd SOFT_RESET\n");
++ ret = -EFAULT;
++ goto done;
++ }
++ Adapter->SurpriseRemoved = TRUE;
++ /* delay to allow hardware complete reset */
++ os_sched_timeout(5);
++ if (priv->MediaConnected == TRUE) {
++ os_stop_queue(priv);
++ os_carrier_off(priv);
++ priv->MediaConnected = FALSE;
++ }
++ Adapter->CmdSize = 0;
++ Adapter->CmdWaitQWoken = TRUE;
++ wake_up_interruptible(&Adapter->cmdwait_q);
++ skb_queue_purge(&priv->adapter->tx_queue);
++ skb_queue_purge(&priv->adapter->cmd_queue);
++ done:
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function processes received packet and forwards it
++ * to kernel/upper layer
++ *
++ * @param priv A pointer to uap_private
++ * @param skb A pointer to skb which includes the received packet
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++int
++uap_process_rx_packet(uap_private * priv, struct sk_buff *skb)
++{
++ int ret = UAP_STATUS_SUCCESS;
++ RxPD *pRxPD;
++ ENTER();
++ priv->adapter->ps_state = PS_STATE_AWAKE;
++ pRxPD = (RxPD *) skb->data;
++ endian_convert_RxPD(pRxPD);
++ DBG_HEXDUMP(DAT_D, "Rx", skb->data, MIN(skb->len, DATA_DUMP_LEN));
++ skb_pull(skb, pRxPD->RxPktOffset);
++ priv->stats.rx_packets++;
++ priv->stats.rx_bytes += skb->len;
++ os_upload_rx_packet(priv, skb);
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function opens the network device
++ *
++ * @param dev A pointer to net_device structure
++ * @return UAP_STATUS_SUCCESS
++ */
++static int
++uap_open(struct net_device *dev)
++{
++ uap_private *priv = (uap_private *) (uap_private *) netdev_priv(dev);
++ uap_adapter *Adapter = priv->adapter;
++ int i = 0;
++
++ ENTER();
++
++ /* On some systems the device open handler will be called before HW ready. */
++ /* Use the following flag check and wait function to work around the issue. */
++ while ((Adapter->HardwareStatus != HWReady) &&
++ (i < MAX_WAIT_DEVICE_READY_COUNT)) {
++ i++;
++ os_sched_timeout(100);
++ }
++ if (i >= MAX_WAIT_DEVICE_READY_COUNT) {
++ PRINTM(FATAL, "HW not ready, uap_open() return failure\n");
++ LEAVE();
++ return UAP_STATUS_FAILURE;
++ }
++
++ if (MODULE_GET == 0)
++ return UAP_STATUS_FAILURE;
++
++ priv->open = TRUE;
++ if (priv->MediaConnected == TRUE) {
++ os_carrier_on(priv);
++ os_start_queue(priv);
++ } else {
++ os_stop_queue(priv);
++ os_carrier_off(priv);
++ }
++ LEAVE();
++ return UAP_STATUS_SUCCESS;
++}
++
++/**
++ * @brief This function closes the network device
++ *
++ * @param dev A pointer to net_device structure
++ * @return UAP_STATUS_SUCCESS
++ */
++static int
++uap_close(struct net_device *dev)
++{
++ uap_private *priv = (uap_private *) netdev_priv(dev);
++
++ ENTER();
++ skb_queue_purge(&priv->adapter->tx_queue);
++ os_stop_queue(priv);
++ os_carrier_off(priv);
++
++ MODULE_PUT;
++ priv->open = FALSE;
++ LEAVE();
++ return UAP_STATUS_SUCCESS;
++}
++
++/**
++ * @brief This function returns the network statistics
++ *
++ * @param dev A pointer to uap_private structure
++ * @return A pointer to net_device_stats structure
++ */
++static struct net_device_stats *
++uap_get_stats(struct net_device *dev)
++{
++ uap_private *priv = (uap_private *) netdev_priv(dev);
++
++ return &priv->stats;
++}
++
++/**
++ * @brief This function sets the MAC address to firmware.
++ *
++ * @param dev A pointer to uap_private structure
++ * @param addr MAC address to set
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++static int
++uap_set_mac_address(struct net_device *dev, void *addr)
++{
++ int ret = UAP_STATUS_SUCCESS;
++ uap_private *priv = (uap_private *) netdev_priv(dev);
++ struct sockaddr *pHwAddr = (struct sockaddr *) addr;
++ u32 CmdSize;
++ HostCmd_DS_COMMAND *cmd;
++ MrvlIEtypes_MacAddr_t *pMacAddrTlv;
++ uap_adapter *Adapter = priv->adapter;
++ struct sk_buff *skb;
++
++ ENTER();
++
++ /* Dump MAC address */
++ DBG_HEXDUMP(CMD_D, "Original MAC addr", dev->dev_addr, ETH_ALEN);
++ DBG_HEXDUMP(CMD_D, "New MAC addr", pHwAddr->sa_data, ETH_ALEN);
++ if (priv->open && (priv->MediaConnected == TRUE)) {
++ os_carrier_on(priv);
++ os_start_queue(priv);
++ }
++ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
++ if (!skb) {
++ PRINTM(ERROR, "No free skb\n");
++ LEAVE();
++ return -ENOMEM;
++ }
++ CmdSize =
++ S_DS_GEN + sizeof(HostCmd_SYS_CONFIG) + sizeof(MrvlIEtypes_MacAddr_t);
++ cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN);
++ cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE);
++ cmd->Size = uap_cpu_to_le16(CmdSize);
++ cmd->params.sys_config.Action = uap_cpu_to_le16(ACTION_SET);
++ pMacAddrTlv =
++ (MrvlIEtypes_MacAddr_t *) ((u8 *) cmd + S_DS_GEN +
++ sizeof(HostCmd_SYS_CONFIG));
++ pMacAddrTlv->Header.Type = uap_cpu_to_le16(MRVL_AP_MAC_ADDRESS_TLV_ID);
++ pMacAddrTlv->Header.Len = uap_cpu_to_le16(ETH_ALEN);
++ memcpy(pMacAddrTlv->ApMacAddr, pHwAddr->sa_data, ETH_ALEN);
++ skb_put(skb, CmdSize + INTF_HEADER_LEN);
++ PRINTM(CMND, "set_mac_address\n");
++ if (UAP_STATUS_SUCCESS !=
++ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) {
++ PRINTM(ERROR, "Fail to set mac address\n");
++ LEAVE();
++ return -EFAULT;
++ }
++ if (!Adapter->CmdSize) {
++ PRINTM(ERROR, "Cmd Size is 0\n");
++ LEAVE();
++ return -EFAULT;
++ }
++ cmd = (HostCmd_DS_COMMAND *) Adapter->CmdBuf;
++ cmd->Result = uap_cpu_to_le16(cmd->Result);
++ if (cmd->Result != UAP_STATUS_SUCCESS) {
++ PRINTM(ERROR, "set mac addrress fail,cmd result=%x\n", cmd->Result);
++ ret = -EFAULT;
++ } else
++ memcpy(dev->dev_addr, pHwAddr->sa_data, ETH_ALEN);
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function handles the timeout of packet
++ * transmission
++ *
++ * @param dev A pointer to net_device structure
++ * @return n/a
++ */
++static void
++uap_tx_timeout(struct net_device *dev)
++{
++ uap_private *priv = (uap_private *) netdev_priv(dev);
++
++ ENTER();
++
++ PRINTM(DATA, "Tx timeout\n");
++ UpdateTransStart(dev);
++ priv->num_tx_timeout++;
++ priv->adapter->IntCounter++;
++ wake_up_interruptible(&priv->MainThread.waitQ);
++
++ LEAVE();
++}
++
++/**
++ * @brief This function handles packet transmission
++ *
++ * @param skb A pointer to sk_buff structure
++ * @param dev A pointer to net_device structure
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++static int
++uap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++ uap_private *priv = (uap_private *) netdev_priv(dev);
++ int ret = UAP_STATUS_SUCCESS;
++
++ ENTER();
++ PRINTM(DATA, "Data <= kernel\n");
++ DBG_HEXDUMP(DAT_D, "Tx", skb->data, MIN(skb->len, DATA_DUMP_LEN));
++ /* skb sanity check */
++ if (!skb->len || (skb->len > MRVDRV_MAXIMUM_ETH_PACKET_SIZE)) {
++ PRINTM(ERROR, "Tx Error: Bad skb length %d : %d\n", skb->len,
++ MRVDRV_MAXIMUM_ETH_PACKET_SIZE);
++ priv->stats.tx_dropped++;
++ kfree(skb);
++ goto done;
++ }
++ skb_queue_tail(&priv->adapter->tx_queue, skb);
++ wake_up_interruptible(&priv->MainThread.waitQ);
++ if (skb_queue_len(&priv->adapter->tx_queue) > TX_HIGH_WATERMARK) {
++ UpdateTransStart(dev);
++ os_stop_queue(priv);
++ }
++ done:
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief ioctl function - entry point
++ *
++ * @param dev A pointer to net_device structure
++ * @param req A pointer to ifreq structure
++ * @param cmd command
++ * @return UAP_STATUS_SUCCESS--success, otherwise fail
++ */
++static int
++uap_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
++{
++ int ret = UAP_STATUS_SUCCESS;
++
++ ENTER();
++
++ PRINTM(CMND, "uap_do_ioctl: ioctl cmd = 0x%x\n", cmd);
++
++ switch (cmd) {
++ case UAPHOSTCMD:
++ ret = uap_hostcmd_ioctl(dev, req);
++ break;
++ case UAP_POWER_MODE:
++ ret = uap_power_mode_ioctl(dev, req);
++ break;
++ default:
++ ret = -EINVAL;
++ break;
++ }
++
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function handles events generated by firmware
++ *
++ * @param priv A pointer to uap_private structure
++ * @param payload A pointer to payload buffer
++ * @param len Length of the payload
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++int
++uap_process_event(uap_private * priv, u8 * payload, uint len)
++{
++ int ret = UAP_STATUS_SUCCESS;
++ uap_adapter *Adapter = priv->adapter;
++ struct sk_buff *skb = NULL;
++ struct nlmsghdr *nlh = NULL;
++ struct sock *sk = Adapter->nl_sk;
++ AP_Event *pEvent;
++
++ ENTER();
++ Adapter->ps_state = PS_STATE_AWAKE;
++ if (len > NL_MAX_PAYLOAD) {
++ PRINTM(ERROR, "event size is too big!!! len=%d\n", len);
++ ret = UAP_STATUS_FAILURE;
++ goto done;
++ }
++ pEvent = (AP_Event *) payload;
++ PRINTM(CMND, "Event: %d\n", pEvent->EventId);
++ switch (pEvent->EventId) {
++ case MICRO_AP_EV_ID_BSS_START:
++ memcpy(priv->uap_dev.netdev->dev_addr, pEvent->MacAddr, ETH_ALEN);
++ DBG_HEXDUMP(CMD_D, "BSS MAC addr", priv->uap_dev.netdev->dev_addr,
++ ETH_ALEN);
++ break;
++ case MICRO_AP_EV_BSS_ACTIVE:
++ // carrier on
++ priv->MediaConnected = TRUE;
++ os_carrier_on(priv);
++ os_start_queue(priv);
++ break;
++ case MICRO_AP_EV_BSS_IDLE:
++ os_stop_queue(priv);
++ os_carrier_off(priv);
++ priv->MediaConnected = FALSE;
++ break;
++ case EVENT_PS_AWAKE:
++ PRINTM(CMND, "UAP: PS_AWAKE\n");
++ Adapter->ps_state = PS_STATE_AWAKE;
++ Adapter->WakeupTries = 0;
++ break;
++ case EVENT_PS_SLEEP:
++ PRINTM(CMND, "UAP: PS_SLEEP\n");
++ Adapter->ps_state = PS_STATE_PRE_SLEEP;
++ break;
++ default:
++ break;
++ }
++ if ((pEvent->EventId == EVENT_PS_AWAKE) ||
++ (pEvent->EventId == EVENT_PS_SLEEP))
++ goto done;
++ if (sk) {
++ /* Allocate skb */
++ if (!(skb = alloc_skb(NLMSG_SPACE(NL_MAX_PAYLOAD), GFP_ATOMIC))) {
++ PRINTM(ERROR, "Could not allocate skb for netlink.\n");
++ ret = UAP_STATUS_FAILURE;
++ goto done;
++ }
++ nlh = (struct nlmsghdr *) skb->data;
++ nlh->nlmsg_len = NLMSG_SPACE(len);
++
++ /* From kernel */
++ nlh->nlmsg_pid = 0;
++ nlh->nlmsg_flags = 0;
++
++ /* Data */
++ skb_put(skb, nlh->nlmsg_len);
++ memcpy(NLMSG_DATA(nlh), payload, len);
++
++ /* From Kernel */
++ NETLINK_CB(skb).portid = 0;
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
++ /* Multicast message */
++ NETLINK_CB(skb).dst_pid = 0;
++#endif
++
++ /* Multicast group number */
++ NETLINK_CB(skb).dst_group = NL_MULTICAST_GROUP;
++
++ /* Send message */
++ netlink_broadcast(sk, skb, 0, NL_MULTICAST_GROUP, GFP_KERNEL);
++
++ ret = UAP_STATUS_SUCCESS;
++ } else {
++ PRINTM(ERROR, "Could not send event through NETLINK. Link down.\n");
++ ret = UAP_STATUS_FAILURE;
++ }
++ done:
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function handles the interrupt. it will change PS
++ * state if applicable. it will wake up main_thread to handle
++ * the interrupt event as well.
++ *
++ * @param priv A pointer to uap_private structure
++ * @return n/a
++ */
++void
++uap_interrupt(uap_private * priv)
++{
++ ENTER();
++ priv->adapter->IntCounter++;
++ priv->adapter->WakeupTries = 0;
++ PRINTM(INFO, "*\n");
++ wake_up_interruptible(&priv->MainThread.waitQ);
++
++ LEAVE();
++
++}
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
++/** Network device handlers */
++static const struct net_device_ops uap_netdev_ops = {
++ .ndo_open = uap_open,
++ .ndo_start_xmit = uap_hard_start_xmit,
++ .ndo_stop = uap_close,
++ .ndo_do_ioctl = uap_do_ioctl,
++ .ndo_set_mac_address = uap_set_mac_address,
++ .ndo_tx_timeout = uap_tx_timeout,
++ .ndo_get_stats = uap_get_stats,
++};
++#endif
++
++/**
++ * @brief This function adds the card. it will probe the
++ * card, allocate the uap_priv and initialize the device.
++ *
++ * @param card A pointer to card
++ * @return A pointer to uap_private structure
++ */
++uap_private *
++uap_add_card(void *card)
++{
++ struct net_device *dev = NULL;
++ uap_private *priv = NULL;
++
++ ENTER();
++
++ if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
++ goto exit_sem_err;
++
++ /* Allocate an Ethernet device */
++ if (!(dev = alloc_etherdev(sizeof(uap_private)))) {
++ PRINTM(FATAL, "Init ethernet device failed!\n");
++ goto error;
++ }
++ priv = (uap_private *) netdev_priv(dev);
++
++ /* Allocate name */
++ if (dev_alloc_name(dev, "uap%d") < 0) {
++ PRINTM(ERROR, "Could not allocate device name!\n");
++ goto error;
++ }
++
++ /* Allocate buffer for uap_adapter */
++ if (!(priv->adapter = kmalloc(sizeof(uap_adapter), GFP_KERNEL))) {
++ PRINTM(FATAL, "Allocate buffer for uap_adapter failed!\n");
++ goto error;
++ }
++ memset(priv->adapter, 0, sizeof(uap_adapter));
++
++ priv->uap_dev.netdev = dev;
++ priv->uap_dev.card = card;
++ priv->MediaConnected = FALSE;
++ uappriv = priv;
++ ((struct sdio_mmc_card *) card)->priv = priv;
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
++ SET_MODULE_OWNER(dev);
++#endif
++
++ /* Setup the OS Interface to our functions */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
++ dev->open = uap_open;
++ dev->stop = uap_close;
++ dev->hard_start_xmit = uap_hard_start_xmit;
++ dev->tx_timeout = uap_tx_timeout;
++ dev->get_stats = uap_get_stats;
++ dev->do_ioctl = uap_do_ioctl;
++ dev->set_mac_address = uap_set_mac_address;
++ dev->set_multicast_list = uap_set_multicast_list;
++#else
++ dev->netdev_ops = &uap_netdev_ops;
++#endif
++ dev->watchdog_timeo = MRVDRV_DEFAULT_WATCHDOG_TIMEOUT;
++ dev->hard_header_len += sizeof(TxPD) + INTF_HEADER_LEN;
++ dev->hard_header_len += HEADER_ALIGNMENT;
++#define NETIF_F_DYNALLOC 16
++ dev->features |= NETIF_F_DYNALLOC;
++ dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
++
++ /* Init SW */
++ if (uap_init_sw(priv)) {
++ PRINTM(FATAL, "Software Init Failed\n");
++ goto error;
++ }
++
++ PRINTM(INFO, "Starting kthread...\n");
++ priv->MainThread.priv = priv;
++ spin_lock_init(&priv->driver_lock);
++ uap_create_thread(uap_service_main_thread, &priv->MainThread,
++ "uap_main_service");
++ while (priv->MainThread.pid == 0) {
++ os_sched_timeout(2);
++ }
++
++ /* Register the device */
++ if (sbi_register_dev(priv) < 0) {
++ PRINTM(FATAL, "Failed to register uap device!\n");
++ goto err_registerdev;
++ }
++#ifdef FW_DNLD_NEEDED
++ SET_NETDEV_DEV(dev, priv->hotplug_device);
++#endif
++
++ /* Init FW and HW */
++ if (uap_init_fw(priv)) {
++ PRINTM(FATAL, "Firmware Init Failed\n");
++ goto err_init_fw;
++ }
++
++ priv->uap_dev.cmd_sent = FALSE;
++ priv->uap_dev.data_sent = FALSE;
++
++ /* Get mac address from firmware */
++ if (uap_get_mac_address(priv)) {
++ PRINTM(FATAL, "Fail to get mac address\n");
++ goto err_init_fw;
++ }
++ /* Register network device */
++ if (register_netdev(dev)) {
++ printk(KERN_ERR "Cannot register network device!\n");
++ goto err_init_fw;
++ }
++#ifdef CONFIG_PROC_FS
++ uap_proc_entry(priv, dev);
++ uap_debug_entry(priv, dev);
++#endif /* CPNFIG_PROC_FS */
++ OS_REL_SEMAPHORE(&AddRemoveCardSem);
++
++ LEAVE();
++ return priv;
++ err_init_fw:
++ sbi_unregister_dev(priv);
++ err_registerdev:
++ ((struct sdio_mmc_card *) card)->priv = NULL;
++ /* Stop the thread servicing the interrupts */
++ priv->adapter->SurpriseRemoved = TRUE;
++ wake_up_interruptible(&priv->MainThread.waitQ);
++ while (priv->MainThread.pid) {
++ os_sched_timeout(1);
++ }
++ error:
++ if (dev) {
++ if (dev->reg_state == NETREG_REGISTERED)
++ unregister_netdev(dev);
++ if (priv->adapter)
++ uap_free_adapter(priv);
++ free_netdev(dev);
++ uappriv = NULL;
++ }
++ OS_REL_SEMAPHORE(&AddRemoveCardSem);
++ exit_sem_err:
++ LEAVE();
++ return NULL;
++}
++
++/**
++ * @brief This function removes the card.
++ *
++ * @param card A pointer to card
++ * @return UAP_STATUS_SUCCESS
++ */
++int
++uap_remove_card(void *card)
++{
++ uap_private *priv = uappriv;
++ uap_adapter *Adapter;
++ struct net_device *dev;
++
++ ENTER();
++
++ if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
++ goto exit_sem_err;
++
++ if (!priv || !(Adapter = priv->adapter)) {
++ goto exit_remove;
++ }
++ Adapter->SurpriseRemoved = TRUE;
++ if (Adapter->cmd_pending == TRUE) {
++ /* Wake up cmd Q */
++ Adapter->CmdWaitQWoken = TRUE;
++ wake_up_interruptible(&Adapter->cmdwait_q);
++ }
++ dev = priv->uap_dev.netdev;
++ if (priv->MediaConnected == TRUE) {
++ os_stop_queue(priv);
++ os_carrier_off(priv);
++ priv->MediaConnected = FALSE;
++ }
++ Adapter->CmdSize = 0;
++ Adapter->CmdWaitQWoken = TRUE;
++ wake_up_interruptible(&Adapter->cmdwait_q);
++ skb_queue_purge(&priv->adapter->tx_queue);
++ skb_queue_purge(&priv->adapter->cmd_queue);
++
++ /* Disable interrupts on the card */
++ sbi_disable_host_int(priv);
++ PRINTM(INFO, "netdev_finish_unregister: %s%s.\n", dev->name,
++ (dev->features & NETIF_F_DYNALLOC) ? "" : ", old style");
++ unregister_netdev(dev);
++ PRINTM(INFO, "Unregister finish\n");
++ wake_up_interruptible(&priv->MainThread.waitQ);
++ while (priv->MainThread.pid) {
++ os_sched_timeout(1);
++ }
++
++ if ((Adapter->nl_sk) && ((Adapter->nl_sk)->sk_socket)) {
++ sock_release((Adapter->nl_sk)->sk_socket);
++ Adapter->nl_sk = NULL;
++ }
++#ifdef CONFIG_PROC_FS
++ uap_debug_remove(priv);
++ uap_proc_remove(priv);
++#endif
++ sbi_unregister_dev(priv);
++ PRINTM(INFO, "Free Adapter\n");
++ uap_free_adapter(priv);
++ priv->uap_dev.netdev = NULL;
++ free_netdev(dev);
++ uappriv = NULL;
++
++ exit_remove:
++ OS_REL_SEMAPHORE(&AddRemoveCardSem);
++ exit_sem_err:
++ LEAVE();
++ return UAP_STATUS_SUCCESS;
++}
++
++/**
++ * @brief This function initializes module.
++ *
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++static int __init
++uap_init_module(void)
++{
++ int ret = UAP_STATUS_SUCCESS;
++ ENTER();
++
++ OS_INIT_SEMAPHORE(&AddRemoveCardSem);
++ ret = sbi_register();
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function cleans module
++ *
++ * @return n/a
++ */
++static void __exit
++uap_cleanup_module(void)
++{
++ ENTER();
++
++ if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
++ goto exit_sem_err;
++
++ if ((uappriv) && (uappriv->adapter)) {
++ uap_func_shutdown(uappriv);
++ }
++ OS_REL_SEMAPHORE(&AddRemoveCardSem);
++ exit_sem_err:
++ sbi_unregister();
++ LEAVE();
++}
++
++module_init(uap_init_module);
++module_exit(uap_cleanup_module);
++module_param(helper_name, charp, 0);
++MODULE_PARM_DESC(helper_name, "Helper name");
++module_param(fw_name, charp, 0);
++MODULE_PARM_DESC(fw_name, "Firmware name");
++
++MODULE_DESCRIPTION("M-UAP Driver");
++MODULE_AUTHOR("Marvell International Ltd.");
++MODULE_VERSION(DRIVER_VERSION);
++MODULE_LICENSE("GPL");
+diff --git a/drivers/net/wireless/libertas_uap/uap_proc.c b/drivers/net/wireless/libertas_uap/uap_proc.c
+new file mode 100644
+index 0000000..d673f56
+--- /dev/null
++++ b/drivers/net/wireless/libertas_uap/uap_proc.c
+@@ -0,0 +1,258 @@
++/** @file uap_proc.c
++ * @brief This file contains functions for proc file.
++ *
++ * Copyright (C) 2008-2009, Marvell International Ltd.
++ *
++ * This software file (the "File") is distributed by Marvell International
++ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
++ * (the "License"). You may use, redistribute and/or modify this File in
++ * accordance with the terms and conditions of the License, a copy of which
++ * is available along with the File in the gpl.txt file or by writing to
++ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++ *
++ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
++ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
++ * this warranty disclaimer.
++ *
++ */
++#ifdef CONFIG_PROC_FS
++#include <linux/proc_fs.h>
++#include <linux/seq_file.h>
++#include "uap_headers.h"
++
++/** /proc directory root */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
++#define PROC_DIR NULL
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
++#define PROC_DIR &proc_root
++#else
++#define PROC_DIR proc_net
++#endif
++
++/********************************************************
++ Local Variables
++********************************************************/
++
++/********************************************************
++ Global Variables
++********************************************************/
++
++/********************************************************
++ Local Functions
++********************************************************/
++
++static int uap_info_proc_show(struct seq_file *s, void *data) {
++ int i;
++ struct net_device *netdev = (struct net_device*)s->private;
++ struct netdev_hw_addr *ha;
++ uap_private *priv = (uap_private *) netdev_priv(netdev);
++
++ seq_printf(s, "driver_name = " "\"uap\"\n");
++ seq_printf(s, "driver_version = %s-(FP%s)", DRIVER_VERSION, FPNUM);
++ seq_printf(s, "\nInterfaceName=\"%s\"\n", netdev->name);
++
++ seq_printf(s, "State=\"%s\"\n",
++ ((priv->MediaConnected ==
++ FALSE) ? "Disconnected" : "Connected"));
++ seq_printf(s, "MACAddress=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n",
++ netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
++ netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]);
++ i = 0;
++ netdev_for_each_mc_addr(ha, netdev) {
++ ++i;
++ }
++ seq_printf(s, "MCCount=\"%d\"\n", i);
++
++ /*
++ * Put out the multicast list
++ */
++ i = 0;
++ netdev_for_each_mc_addr(ha, netdev) {
++ seq_printf(s,
++ "MCAddr[%d]=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n",
++ i++,
++ ha->addr[0], ha->addr[1],
++ ha->addr[2], ha->addr[3],
++ ha->addr[4], ha->addr[5]);
++ }
++
++ seq_printf(s, "num_tx_bytes = %lu\n", priv->stats.tx_bytes);
++ seq_printf(s, "num_rx_bytes = %lu\n", priv->stats.rx_bytes);
++ seq_printf(s, "num_tx_pkts = %lu\n", priv->stats.tx_packets);
++ seq_printf(s, "num_rx_pkts = %lu\n", priv->stats.rx_packets);
++ seq_printf(s, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped);
++ seq_printf(s, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped);
++ seq_printf(s, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors);
++ seq_printf(s, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors);
++ seq_printf(s, "num_tx_timeout = %u\n", priv->num_tx_timeout);
++ seq_printf(s, "carrier %s\n",
++ ((netif_carrier_ok(priv->uap_dev.netdev)) ? "on" : "off"));
++ seq_printf(s, "tx queue %s\n",
++ ((netif_queue_stopped(priv->uap_dev.netdev)) ? "stopped" :
++ "started"));
++
++ return 0;
++}
++
++static int uap_info_proc_open(struct inode *inode, struct file *file) {
++ return single_open(file, uap_info_proc_show, PDE_DATA(inode));
++}
++
++static int uap_hwstatus_proc_show(struct seq_file *s, void *data) {
++ struct net_device *netdev = (struct net_device*)s->private;
++ uap_private *priv = (uap_private *) netdev_priv(netdev);
++
++ MODULE_GET;
++ seq_printf(s, "%d\n", priv->adapter->HardwareStatus);
++ MODULE_PUT;
++
++ return 0;
++}
++
++static int uap_hwstatus_proc_open(struct inode *inode, struct file *file) {
++ return single_open(file, uap_hwstatus_proc_show, PDE_DATA(inode));
++}
++
++static ssize_t uap_hwstatus_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *data) {
++ struct net_device *netdev = (struct net_device *)PDE_DATA(file_inode(file));
++ uap_private *priv = (uap_private *) netdev_priv(netdev);
++
++ int hwstatus;
++ char value[10];
++
++ if (count > sizeof(value))
++ return count;
++
++ if (copy_from_user(&value, buffer, count))
++ return -EFAULT;
++
++ hwstatus = string_to_number(value);
++ switch (hwstatus) {
++ case HWReset:
++ PRINTM(MSG, "reset hw\n");
++ uap_soft_reset(priv);
++ priv->adapter->HardwareStatus = HWReset;
++ break;
++ default:
++ break;
++ }
++
++ MODULE_PUT;
++ return count;
++}
++
++static const struct file_operations uap_info_proc_fops = {
++ .owner = THIS_MODULE,
++ .open = uap_info_proc_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static const struct file_operations uap_hwstatus_proc_fops = {
++ .owner = THIS_MODULE,
++ .open = uap_hwstatus_proc_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++ .write = uap_hwstatus_proc_write,
++};
++
++/********************************************************
++ Global Functions
++********************************************************/
++/**
++ * @brief create uap proc file
++ *
++ * @param priv pointer uap_private
++ * @param dev pointer net_device
++ * @return N/A
++ */
++void
++uap_proc_entry(uap_private * priv, struct net_device *dev)
++{
++ PRINTM(INFO, "Creating Proc Interface\n");
++ /* Check if uap directory already exists */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
++ struct proc_dir_entry *r = PROC_DIR;
++
++ for (r = r->subdir; r; r = r->next) {
++ if (r->namelen && !strcmp("uap", r->name)) {
++ /* Directory exists */
++ PRINTM(WARN, "proc directory already exists!\n");
++ priv->proc_uap = r;
++ break;
++ }
++ }
++#endif
++ if (!priv->proc_uap) {
++ priv->proc_uap = proc_mkdir("uap", PROC_DIR);
++ if (!priv->proc_uap)
++ return;
++ }
++ priv->proc_entry = proc_mkdir(dev->name, priv->proc_uap);
++
++ if (priv->proc_entry) {
++ proc_create_data("info", 0644, priv->proc_entry, &uap_info_proc_fops, dev);
++ proc_create_data("hwinfo", 0644, priv->proc_entry, &uap_hwstatus_proc_fops, dev);
++ }
++}
++
++/**
++ * @brief remove proc file
++ *
++ * @param priv pointer uap_private
++ * @return N/A
++ */
++void
++uap_proc_remove(uap_private * priv)
++{
++ if (priv->proc_uap) {
++ if (priv->proc_entry) {
++ remove_proc_entry("info", priv->proc_entry);
++ remove_proc_entry("hwstatus", priv->proc_entry);
++ }
++ remove_proc_entry(priv->uap_dev.netdev->name, priv->proc_uap);
++ }
++}
++
++/**
++ * @brief convert string to number
++ *
++ * @param s pointer to numbered string
++ * @return converted number from string s
++ */
++int
++string_to_number(char *s)
++{
++ int r = 0;
++ int base = 0;
++ int pn = 1;
++
++ if (strncmp(s, "-", 1) == 0) {
++ pn = -1;
++ s++;
++ }
++ if ((strncmp(s, "0x", 2) == 0) || (strncmp(s, "0X", 2) == 0)) {
++ base = 16;
++ s += 2;
++ } else
++ base = 10;
++
++ for (s = s; *s != 0; s++) {
++ if ((*s >= '0') && (*s <= '9'))
++ r = (r * base) + (*s - '0');
++ else if ((*s >= 'A') && (*s <= 'F'))
++ r = (r * base) + (*s - 'A' + 10);
++ else if ((*s >= 'a') && (*s <= 'f'))
++ r = (r * base) + (*s - 'a' + 10);
++ else
++ break;
++ }
++
++ return (r * pn);
++}
++
++#endif
+diff --git a/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c b/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c
+new file mode 100644
+index 0000000..86f55b5
+--- /dev/null
++++ b/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c
+@@ -0,0 +1,1428 @@
++/** @file uap_sdio_mmc.c
++ * @brief This file contains SDIO IF (interface) module
++ * related functions.
++ *
++ * Copyright (C) 2007-2009, Marvell International Ltd.
++ *
++ * This software file (the "File") is distributed by Marvell International
++ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
++ * (the "License"). You may use, redistribute and/or modify this File in
++ * accordance with the terms and conditions of the License, a copy of which
++ * is available along with the File in the gpl.txt file or by writing to
++ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++ *
++ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
++ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
++ * this warranty disclaimer.
++ *
++ */
++/****************************************************
++Change log:
++****************************************************/
++
++#include "uap_sdio_mmc.h"
++
++#include <linux/firmware.h>
++
++/** define SDIO block size */
++/* We support up to 480-byte block size due to FW buffer limitation. */
++#define SD_BLOCK_SIZE 256
++
++/** define allocated buffer size */
++#define ALLOC_BUF_SIZE (((MAX(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, \
++ MRVDRV_SIZE_OF_CMD_BUFFER) + INTF_HEADER_LEN \
++ + SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE) * SD_BLOCK_SIZE)
++
++/** Max retry number of CMD53 write */
++#define MAX_WRITE_IOMEM_RETRY 2
++
++/********************************************************
++ Local Variables
++********************************************************/
++
++/** SDIO Rx unit */
++static u8 sdio_rx_unit = 0;
++
++/**Interrupt status */
++static u8 sd_ireg = 0;
++/********************************************************
++ Global Variables
++********************************************************/
++extern u8 *helper_name;
++extern u8 *fw_name;
++/** Default helper name */
++#define DEFAULT_HELPER_NAME "mrvl/helper_sd.bin"
++/** Default firmware name */
++#define DEFAULT_FW_NAME "mrvl/sd8688_ap.bin"
++
++/********************************************************
++ Local Functions
++********************************************************/
++/**
++ * @brief This function reads the IO register.
++ *
++ * @param priv A pointer to uap_private structure
++ * @param reg register to be read
++ * @param dat A pointer to variable that keeps returned value
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++static int
++sbi_read_ioreg(uap_private * priv, u32 reg, u8 * dat)
++{
++ struct sdio_mmc_card *card;
++ int ret = UAP_STATUS_FAILURE;
++
++ ENTER();
++
++ card = priv->uap_dev.card;
++ if (!card || !card->func) {
++ PRINTM(ERROR, "sbi_read_ioreg(): card or function is NULL!\n");
++ goto done;
++ }
++
++ *dat = sdio_readb(card->func, reg, &ret);
++ if (ret) {
++ PRINTM(ERROR, "sbi_read_ioreg(): sdio_readb failed! ret=%d\n", ret);
++ goto done;
++ }
++
++ PRINTM(INFO, "sbi_read_ioreg() priv=%p func=%d reg=%#x dat=%#x\n", priv,
++ card->func->num, reg, *dat);
++
++ done:
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function writes the IO register.
++ *
++ * @param priv A pointer to uap_private structure
++ * @param reg register to be written
++ * @param dat the value to be written
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++static int
++sbi_write_ioreg(uap_private * priv, u32 reg, u8 dat)
++{
++ struct sdio_mmc_card *card;
++ int ret = UAP_STATUS_FAILURE;
++
++ ENTER();
++
++ card = priv->uap_dev.card;
++ if (!card || !card->func) {
++ PRINTM(ERROR, "sbi_write_ioreg(): card or function is NULL!\n");
++ goto done;
++ }
++
++ PRINTM(INFO, "sbi_write_ioreg() priv=%p func=%d reg=%#x dat=%#x\n", priv,
++ card->func->num, reg, dat);
++
++ sdio_writeb(card->func, dat, reg, &ret);
++ if (ret) {
++ PRINTM(ERROR, "sbi_write_ioreg(): sdio_readb failed! ret=%d\n", ret);
++ goto done;
++ }
++
++ done:
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function get rx_unit value
++ *
++ * @param priv A pointer to uap_private structure
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++static int
++sd_get_rx_unit(uap_private * priv)
++{
++ int ret = UAP_STATUS_SUCCESS;
++ u8 reg;
++
++ ENTER();
++
++ ret = sbi_read_ioreg(priv, CARD_RX_UNIT_REG, ®);
++ if (ret == UAP_STATUS_SUCCESS)
++ sdio_rx_unit = reg;
++
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function reads rx length
++ *
++ * @param priv A pointer to uap_private structure
++ * @param dat A pointer to keep returned data
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++static int
++sd_read_rx_len(uap_private * priv, u16 * dat)
++{
++ int ret = UAP_STATUS_SUCCESS;
++ u8 reg;
++
++ ENTER();
++
++ ret = sbi_read_ioreg(priv, CARD_RX_LEN_REG, ®);
++ if (ret == UAP_STATUS_SUCCESS)
++ *dat = (u16) reg << sdio_rx_unit;
++
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function reads fw status registers
++ *
++ * @param priv A pointer to uap_private structure
++ * @param dat A pointer to keep returned data
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++static int
++sd_read_firmware_status(uap_private * priv, u16 * dat)
++{
++ int ret = UAP_STATUS_SUCCESS;
++ u8 fws0;
++ u8 fws1;
++
++ ENTER();
++
++ ret = sbi_read_ioreg(priv, CARD_FW_STATUS0_REG, &fws0);
++ if (ret < 0) {
++ LEAVE();
++ return UAP_STATUS_FAILURE;
++ }
++
++ ret = sbi_read_ioreg(priv, CARD_FW_STATUS1_REG, &fws1);
++ if (ret < 0) {
++ LEAVE();
++ return UAP_STATUS_FAILURE;
++ }
++
++ *dat = (((u16) fws1) << 8) | fws0;
++
++ LEAVE();
++ return UAP_STATUS_SUCCESS;
++}
++
++/**
++ * @brief This function polls the card status register.
++ *
++ * @param priv A pointer to uap_private structure
++ * @param bits the bit mask
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++static int
++mv_sdio_poll_card_status(uap_private * priv, u8 bits)
++{
++ int tries;
++ u8 cs;
++
++ ENTER();
++
++ for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
++ if (sbi_read_ioreg(priv, CARD_STATUS_REG, &cs) < 0)
++ break;
++ else if ((cs & bits) == bits) {
++ LEAVE();
++ return UAP_STATUS_SUCCESS;
++ }
++ udelay(10);
++ }
++
++ PRINTM(WARN, "mv_sdio_poll_card_status failed, tries = %d\n", tries);
++
++ LEAVE();
++ return UAP_STATUS_FAILURE;
++}
++
++/**
++ * @brief This function set the sdio bus width.
++ *
++ * @param priv A pointer to uap_private structure
++ * @param mode 1--1 bit mode, 4--4 bit mode
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++#if 0
++static int
++sdio_set_bus_width(uap_private * priv, u8 mode)
++{
++ ENTER();
++ LEAVE();
++ return UAP_STATUS_SUCCESS;
++}
++#endif
++
++/**
++ * @brief This function reads data from the card.
++ *
++ * @param priv A pointer to uap_private structure
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++static int
++sd_card_to_host(uap_private * priv)
++{
++ int ret = UAP_STATUS_SUCCESS;
++ u16 buf_len = 0;
++ int buf_block_len;
++ int blksz;
++ struct sk_buff *skb = NULL;
++ u16 type;
++ u8 *payload = NULL;
++ struct sdio_mmc_card *card = priv->uap_dev.card;
++
++ ENTER();
++
++ if (!card || !card->func) {
++ PRINTM(ERROR, "card or function is NULL!\n");
++ ret = UAP_STATUS_FAILURE;
++ goto exit;
++ }
++
++ /* Read the length of data to be transferred */
++ ret = sd_read_rx_len(priv, &buf_len);
++ if (ret < 0) {
++ PRINTM(ERROR, "card_to_host, read scratch reg failed\n");
++ ret = UAP_STATUS_FAILURE;
++ goto exit;
++ }
++
++ /* Allocate buffer */
++ blksz = SD_BLOCK_SIZE;
++ buf_block_len = (buf_len + blksz - 1) / blksz;
++ if (buf_len <= INTF_HEADER_LEN || (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
++ PRINTM(ERROR, "card_to_host, invalid packet length: %d\n", buf_len);
++ ret = UAP_STATUS_FAILURE;
++ goto exit;
++ }
++#ifdef PXA3XX_DMA_ALIGN
++ skb = dev_alloc_skb(buf_block_len * blksz + PXA3XX_DMA_ALIGNMENT);
++#else
++ skb = dev_alloc_skb(buf_block_len * blksz);
++#endif
++ if (skb == NULL) {
++ PRINTM(WARN, "No free skb\n");
++ goto exit;
++ }
++#ifdef PXA3XX_DMA_ALIGN
++ if ((u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1)) {
++ skb_put(skb, (u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1));
++ skb_pull(skb, (u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1));
++ }
++#endif /* PXA3XX_DMA_ALIGN */
++
++ payload = skb->tail;
++ ret = sdio_readsb(card->func, payload, priv->uap_dev.ioport,
++ buf_block_len * blksz);
++ if (ret < 0) {
++ PRINTM(ERROR, "card_to_host, read iomem failed: %d\n", ret);
++ ret = UAP_STATUS_FAILURE;
++ goto exit;
++ }
++ HEXDUMP("SDIO Blk Rd", payload, blksz * buf_block_len);
++ /*
++ * This is SDIO specific header
++ * u16 length,
++ * u16 type (MV_TYPE_DAT = 0, MV_TYPE_CMD = 1, MV_TYPE_EVENT = 3)
++ */
++ buf_len = uap_le16_to_cpu(*(u16 *) & payload[0]);
++ type = uap_le16_to_cpu(*(u16 *) & payload[2]);
++ switch (type) {
++ case MV_TYPE_EVENT:
++ skb_put(skb, buf_len);
++ skb_pull(skb, INTF_HEADER_LEN);
++ uap_process_event(priv, skb->data, skb->len);
++ kfree_skb(skb);
++ skb = NULL;
++ break;
++ case MV_TYPE_CMD:
++ skb_put(skb, buf_len);
++ skb_pull(skb, INTF_HEADER_LEN);
++ priv->adapter->cmd_pending = FALSE;
++ if (priv->adapter->cmd_wait_option ==
++ HostCmd_OPTION_WAITFORRSP_SLEEPCONFIRM) {
++ priv->adapter->cmd_wait_option = FALSE;
++ uap_process_sleep_confirm_resp(priv, skb->data, skb->len);
++ } else if (priv->adapter->cmd_wait_option) {
++ memcpy(priv->adapter->CmdBuf, skb->data, skb->len);
++ priv->adapter->CmdSize = skb->len;
++ priv->adapter->cmd_wait_option = FALSE;
++ priv->adapter->CmdWaitQWoken = TRUE;
++ wake_up_interruptible(&priv->adapter->cmdwait_q);
++ }
++ kfree_skb(skb);
++ skb = NULL;
++ break;
++ case MV_TYPE_DAT:
++ skb_put(skb, buf_len);
++ skb_pull(skb, INTF_HEADER_LEN);
++ uap_process_rx_packet(priv, skb);
++ break;
++ default:
++ priv->stats.rx_errors++;
++ priv->stats.rx_dropped++;
++ /* Driver specified event and command resp should be handle here */
++ PRINTM(INFO, "Unknown PKT type:%d\n", type);
++ kfree_skb(skb);
++ skb = NULL;
++ break;
++ }
++ exit:
++ if (ret) {
++ if (skb)
++ kfree_skb(skb);
++ }
++
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function enables the host interrupts mask
++ *
++ * @param priv A pointer to uap_private structure
++ * @param mask the interrupt mask
++ * @return UAP_STATUS_SUCCESS
++ */
++static int
++enable_host_int_mask(uap_private * priv, u8 mask)
++{
++ int ret = UAP_STATUS_SUCCESS;
++
++ ENTER();
++
++ /* Simply write the mask to the register */
++ ret = sbi_write_ioreg(priv, HOST_INT_MASK_REG, mask);
++
++ if (ret) {
++ PRINTM(WARN, "Unable to enable the host interrupt!\n");
++ ret = UAP_STATUS_FAILURE;
++ }
++
++ LEAVE();
++ return ret;
++}
++
++/** @brief This function disables the host interrupts mask.
++ *
++ * @param priv A pointer to uap_private structure
++ * @param mask the interrupt mask
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++static int
++disable_host_int_mask(uap_private * priv, u8 mask)
++{
++ int ret = UAP_STATUS_SUCCESS;
++ u8 host_int_mask;
++
++ ENTER();
++
++ /* Read back the host_int_mask register */
++ ret = sbi_read_ioreg(priv, HOST_INT_MASK_REG, &host_int_mask);
++ if (ret) {
++ ret = UAP_STATUS_FAILURE;
++ goto done;
++ }
++
++ /* Update with the mask and write back to the register */
++ host_int_mask &= ~mask;
++ ret = sbi_write_ioreg(priv, HOST_INT_MASK_REG, host_int_mask);
++ if (ret < 0) {
++ PRINTM(WARN, "Unable to diable the host interrupt!\n");
++ ret = UAP_STATUS_FAILURE;
++ goto done;
++ }
++
++ done:
++ LEAVE();
++ return ret;
++}
++
++/********************************************************
++ Global Functions
++********************************************************/
++
++/**
++ * @brief This function handles the interrupt.
++ *
++ * @param func A pointer to sdio_func structure.
++ * @return n/a
++ */
++static void
++sbi_interrupt(struct sdio_func *func)
++{
++ struct sdio_mmc_card *card;
++ uap_private *priv;
++ u8 ireg = 0;
++ int ret = UAP_STATUS_SUCCESS;
++
++ ENTER();
++
++ card = sdio_get_drvdata(func);
++ if (!card || !card->priv) {
++ PRINTM(MSG, "%s: sbi_interrupt(%p) card or priv is NULL, card=%p\n",
++ __FUNCTION__, func, card);
++ LEAVE();
++ return;
++ }
++ priv = card->priv;
++#ifdef FW_WAKEUP_TIME
++ if ((priv->adapter->wt_pwrup_sending != 0L) &&
++ (priv->adapter->wt_int == 0L))
++ priv->adapter->wt_int = get_utimeofday();
++#endif
++
++ ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret);
++ if (ret) {
++ PRINTM(WARN, "sdio_read_ioreg: read int status register failed\n");
++ goto done;
++ }
++ if (ireg != 0) {
++ /*
++ * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
++ * Clear the interrupt status register and re-enable the interrupt
++ */
++ PRINTM(INFO, "sdio_ireg = 0x%x\n", ireg);
++ sdio_writeb(card->func,
++ ~(ireg) & (DN_LD_HOST_INT_STATUS | UP_LD_HOST_INT_STATUS),
++ HOST_INTSTATUS_REG, &ret);
++ if (ret) {
++ PRINTM(WARN,
++ "sdio_write_ioreg: clear int status register failed\n");
++ goto done;
++ }
++ }
++ OS_INT_DISABLE;
++ sd_ireg |= ireg;
++ OS_INT_RESTORE;
++
++ uap_interrupt(priv);
++ done:
++ LEAVE();
++}
++
++/**
++ * @brief This function probe the card
++ *
++ * @param func A pointer to sdio_func structure
++ * @param id A pointer to structure sd_device_id
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++static int
++uap_probe(struct sdio_func *func, const struct sdio_device_id *id)
++{
++ int ret = UAP_STATUS_FAILURE;
++ struct sdio_mmc_card *card = NULL;
++
++ ENTER();
++
++ PRINTM(MSG, "%s: vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n",
++ __FUNCTION__, func->vendor, func->device, func->class, func->num);
++
++ card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL);
++ if (!card) {
++ ret = -ENOMEM;
++ goto done;
++ }
++
++ card->func = func;
++
++ if (!uap_add_card(card)) {
++ PRINTM(ERROR, "%s: uap_add_callback failed\n", __FUNCTION__);
++ kfree(card);
++ ret = UAP_STATUS_FAILURE;
++ goto done;
++ }
++
++ ret = UAP_STATUS_SUCCESS;
++
++ done:
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function removes the card
++ *
++ * @param func A pointer to sdio_func structure
++ * @return N/A
++ */
++static void
++uap_remove(struct sdio_func *func)
++{
++ struct sdio_mmc_card *card;
++
++ ENTER();
++
++ if (func) {
++ card = sdio_get_drvdata(func);
++ if (card) {
++ uap_remove_card(card);
++ kfree(card);
++ }
++ }
++
++ LEAVE();
++}
++
++#ifdef CONFIG_PM
++/**
++ * @brief This function handles client driver suspend
++ *
++ * @param func A pointer to sdio_func structure
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++int
++uap_suspend(struct sdio_func *func)
++{
++ ENTER();
++ LEAVE();
++ return 0;
++}
++
++/**
++ * @brief This function handles client driver resume
++ *
++ * @param func A pointer to sdio_func structure
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++int
++uap_resume(struct sdio_func *func)
++{
++ ENTER();
++ LEAVE();
++ return 0;
++}
++#endif
++
++/** Device ID for SD8688 */
++#define SD_DEVICE_ID_8688_UAP 0x9104
++/** UAP IDs */
++static const struct sdio_device_id uap_ids[] = {
++ {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SD_DEVICE_ID_8688_UAP)},
++ {},
++};
++
++MODULE_DEVICE_TABLE(sdio, uap_ids);
++
++static struct sdio_driver uap_sdio = {
++ .name = "uap_sdio",
++ .id_table = uap_ids,
++ .probe = uap_probe,
++ .remove = uap_remove,
++#ifdef CONFIG_PM
++/* .suspend = uap_suspend, */
++/* .resume = uap_resume, */
++#endif
++
++};
++
++/**
++ * @brief This function registers the IF module in bus driver.
++ *
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++int __init
++sbi_register()
++{
++ int ret = UAP_STATUS_SUCCESS;
++
++ ENTER();
++
++ /* SDIO Driver Registration */
++ if (sdio_register_driver(&uap_sdio) != 0) {
++ PRINTM(FATAL, "SDIO Driver Registration Failed \n");
++ ret = UAP_STATUS_FAILURE;
++ }
++
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function de-registers the IF module in bus driver.
++ *
++ * @return n/a
++ */
++void __exit
++sbi_unregister(void)
++{
++ ENTER();
++
++ /* SDIO Driver Unregistration */
++ sdio_unregister_driver(&uap_sdio);
++
++ LEAVE();
++}
++
++/**
++ * @brief This function checks the interrupt status and handle it accordingly.
++ *
++ * @param priv A pointer to uap_private structure
++ * @param ireg A pointer to variable that keeps returned value
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++int
++sbi_get_int_status(uap_private * priv, u8 * ireg)
++{
++ int ret = UAP_STATUS_SUCCESS;
++ u8 sdio_ireg = 0;
++ struct sdio_mmc_card *card = priv->uap_dev.card;
++
++ ENTER();
++
++ *ireg = 0;
++ OS_INT_DISABLE;
++ sdio_ireg = sd_ireg;
++ sd_ireg = 0;
++ OS_INT_RESTORE;
++
++ sdio_claim_host(card->func);
++
++ if (sdio_ireg & DN_LD_HOST_INT_STATUS) { /* tx_done INT */
++ if (!priv->uap_dev.cmd_sent) { /* tx_done already received */
++ PRINTM(INFO,
++ "warning: tx_done already received: tx_dnld_rdy=0x%x int status=0x%x\n",
++ priv->uap_dev.cmd_sent, sdio_ireg);
++ } else {
++ priv->uap_dev.cmd_sent = FALSE;
++ priv->uap_dev.data_sent = FALSE;
++ if ( (priv->uap_dev.netdev->reg_state == NETREG_REGISTERED) && (skb_queue_len(&priv->adapter->tx_queue) < TX_LOW_WATERMARK)) {
++ os_start_queue(priv);
++ }
++ }
++ }
++ if (sdio_ireg & UP_LD_HOST_INT_STATUS) {
++ sd_card_to_host(priv);
++ }
++
++ *ireg = sdio_ireg;
++ ret = UAP_STATUS_SUCCESS;
++ sdio_release_host(card->func);
++
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function disables the host interrupts.
++ *
++ * @param priv A pointer to uap_private structure
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++int
++sbi_disable_host_int(uap_private * priv)
++{
++ struct sdio_mmc_card *card = priv->uap_dev.card;
++ int ret;
++
++ ENTER();
++
++ sdio_claim_host(card->func);
++ ret = disable_host_int_mask(priv, HIM_DISABLE);
++ sdio_release_host(card->func);
++
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function enables the host interrupts.
++ *
++ * @param priv A pointer to uap_private structure
++ * @return UAP_STATUS_SUCCESS
++ */
++int
++sbi_enable_host_int(uap_private * priv)
++{
++ struct sdio_mmc_card *card = priv->uap_dev.card;
++ int ret;
++
++ ENTER();
++
++ sdio_claim_host(card->func);
++ ret = enable_host_int_mask(priv, HIM_ENABLE);
++ sdio_release_host(card->func);
++
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function de-registers the device.
++ *
++ * @param priv A pointer to uap_private structure
++ * @return UAP_STATUS_SUCCESS
++ */
++int
++sbi_unregister_dev(uap_private * priv)
++{
++ struct sdio_mmc_card *card = priv->uap_dev.card;
++
++ ENTER();
++
++ if (!card || !card->func) {
++ PRINTM(ERROR, "Error: card or function is NULL!\n");
++ goto done;
++ }
++
++ sdio_claim_host(card->func);
++ sdio_release_irq(card->func);
++ sdio_disable_func(card->func);
++ sdio_release_host(card->func);
++
++ sdio_set_drvdata(card->func, NULL);
++
++ done:
++ LEAVE();
++ return UAP_STATUS_SUCCESS;
++}
++
++/**
++ * @brief This function registers the device.
++ *
++ * @param priv A pointer to uap_private structure
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++int
++sbi_register_dev(uap_private * priv)
++{
++ int ret = UAP_STATUS_FAILURE;
++ u8 reg;
++ struct sdio_mmc_card *card = priv->uap_dev.card;
++ struct sdio_func *func;
++
++ ENTER();
++
++ if (!card || !card->func) {
++ PRINTM(ERROR, "Error: card or function is NULL!\n");
++ goto done;
++ }
++
++ func = card->func;
++
++ /* Initialize the private structure */
++ priv->uap_dev.ioport = 0;
++
++ sdio_claim_host(func);
++
++ ret = sdio_enable_func(func);
++ if (ret) {
++ PRINTM(FATAL, "sdio_enable_func() failed: ret=%d\n", ret);
++ goto release_host;
++ }
++
++ ret = sdio_claim_irq(func, sbi_interrupt);
++ if (ret) {
++ PRINTM(FATAL, "sdio_claim_irq failed: ret=%d\n", ret);
++ goto disable_func;
++ }
++
++ /* Read the IO port */
++ ret = sbi_read_ioreg(priv, IO_PORT_0_REG, ®);
++ if (ret)
++ goto release_irq;
++ else
++ priv->uap_dev.ioport |= reg;
++
++ ret = sbi_read_ioreg(priv, IO_PORT_1_REG, ®);
++ if (ret)
++ goto release_irq;
++ else
++ priv->uap_dev.ioport |= (reg << 8);
++
++ ret = sbi_read_ioreg(priv, IO_PORT_2_REG, ®);
++ if (ret)
++ goto release_irq;
++ else
++ priv->uap_dev.ioport |= (reg << 16);
++
++ PRINTM(INFO, "SDIO FUNC #%d IO port: 0x%x\n", func->num,
++ priv->uap_dev.ioport);
++
++ ret = sdio_set_block_size(card->func, SD_BLOCK_SIZE);
++ if (ret) {
++ PRINTM(ERROR, "%s: cannot set SDIO block size\n", __FUNCTION__);
++ ret = UAP_STATUS_FAILURE;
++ goto release_irq;
++ }
++ priv->hotplug_device = &func->dev;
++
++ if (helper_name == NULL) {
++ helper_name = DEFAULT_HELPER_NAME;
++ }
++ if (fw_name == NULL) {
++ fw_name = DEFAULT_FW_NAME;
++ }
++ sdio_release_host(func);
++
++ sdio_set_drvdata(func, card);
++
++ ret = UAP_STATUS_SUCCESS;
++ goto done;
++
++ release_irq:
++ sdio_release_irq(func);
++ disable_func:
++ sdio_disable_func(func);
++ release_host:
++ sdio_release_host(func);
++
++ done:
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function sends data to the card.
++ *
++ * @param priv A pointer to uap_private structure
++ * @param payload A pointer to the data/cmd buffer
++ * @param nb the length of data/cmd
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++int
++sbi_host_to_card(uap_private * priv, u8 * payload, u16 nb)
++{
++ struct sdio_mmc_card *card = priv->uap_dev.card;
++ int ret = UAP_STATUS_SUCCESS;
++ int buf_block_len;
++ int blksz;
++ int i = 0;
++ u8 *buf = NULL;
++#ifdef PXA3XX_DMA_ALIGN
++ void *tmpbuf = NULL;
++ int tmpbufsz;
++#endif
++
++ ENTER();
++
++ if (!card || !card->func) {
++ PRINTM(ERROR, "card or function is NULL!\n");
++ LEAVE();
++ return UAP_STATUS_FAILURE;
++ }
++ buf = payload;
++#ifdef PXA3XX_DMA_ALIGN
++ if ((u32) payload & (PXA3XX_DMA_ALIGNMENT - 1)) {
++ tmpbufsz = ALIGN_SZ(nb, PXA3XX_DMA_ALIGNMENT);
++ tmpbuf = kmalloc(tmpbufsz, GFP_KERNEL);
++ memset(tmpbuf, 0, tmpbufsz);
++ /* Ensure 8-byte aligned CMD buffer */
++ buf = (u8 *) ALIGN_ADDR(tmpbuf, PXA3XX_DMA_ALIGNMENT);
++ memcpy(buf, payload, nb);
++ }
++#endif
++ /* Allocate buffer and copy payload */
++ blksz = SD_BLOCK_SIZE;
++ buf_block_len = (nb + blksz - 1) / blksz;
++ sdio_claim_host(card->func);
++#define MAX_WRITE_IOMEM_RETRY 2
++ priv->uap_dev.cmd_sent = TRUE;
++ priv->uap_dev.data_sent = TRUE;
++ do {
++ /* Transfer data to card */
++ ret = sdio_writesb(card->func, priv->uap_dev.ioport, buf,
++ buf_block_len * blksz);
++ if (ret < 0) {
++ i++;
++ PRINTM(ERROR, "host_to_card, write iomem (%d) failed: %d\n", i,
++ ret);
++ ret = UAP_STATUS_FAILURE;
++ if (i > MAX_WRITE_IOMEM_RETRY)
++ goto exit;
++ } else {
++ HEXDUMP("SDIO Blk Wr", payload, nb);
++ }
++ } while (ret == UAP_STATUS_FAILURE);
++ exit:
++ sdio_release_host(card->func);
++#ifdef PXA3XX_DMA_ALIGN
++ if (tmpbuf)
++ kfree(tmpbuf);
++#endif
++ if (ret == UAP_STATUS_FAILURE) {
++ priv->uap_dev.cmd_sent = FALSE;
++ priv->uap_dev.data_sent = FALSE;
++ }
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function reads CIS information.
++ *
++ * @param priv A pointer to uap_private structure
++ * @param cisinfo A pointer to CIS information output buffer
++ * @param cislen A pointer to length of CIS info output buffer
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++#if 0
++static int
++sbi_get_cis_info(uap_private * priv, void *cisinfo, int *cislen)
++{
++#define CIS_PTR (0x8000)
++ struct sdio_mmc_card *card = priv->uap_dev.card;
++ unsigned int i, cis_ptr = CIS_PTR;
++ int ret = UAP_STATUS_FAILURE;
++
++ ENTER();
++
++ if (!card || !card->func) {
++ PRINTM(ERROR, "sbi_get_cis_info(): card or function is NULL!\n");
++ goto exit;
++ }
++#define MAX_SDIO_CIS_INFO_LEN (256)
++ if (!cisinfo || (*cislen < MAX_SDIO_CIS_INFO_LEN)) {
++ PRINTM(WARN, "ERROR! get_cis_info: insufficient buffer passed\n");
++ goto exit;
++ }
++
++ *cislen = MAX_SDIO_CIS_INFO_LEN;
++
++ sdio_claim_host(card->func);
++
++ PRINTM(INFO, "cis_ptr=%#x\n", cis_ptr);
++
++ /* Read the Tuple Data */
++ for (i = 0; i < *cislen; i++) {
++ ((unsigned char *) cisinfo)[i] =
++ sdio_readb(card->func, cis_ptr + i, &ret);
++ if (ret) {
++ PRINTM(WARN, "get_cis_info error: ret=%d\n", ret);
++ ret = UAP_STATUS_FAILURE;
++ goto done;
++ }
++ PRINTM(INFO, "cisinfo[%d]=%#x\n", i, ((unsigned char *) cisinfo)[i]);
++ }
++
++ done:
++ sdio_release_host(card->func);
++ exit:
++ LEAVE();
++ return ret;
++}
++#endif
++/**
++ * @brief This function downloads helper image to the card.
++ *
++ * @param priv A pointer to uap_private structure
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++int
++sbi_prog_helper(uap_private * priv)
++{
++ struct sdio_mmc_card *card = priv->uap_dev.card;
++ u8 *helper = NULL;
++ int helperlen;
++ int ret = UAP_STATUS_SUCCESS;
++ void *tmphlprbuf = NULL;
++ int tmphlprbufsz;
++ u8 *hlprbuf;
++ int hlprblknow;
++ u32 tx_len;
++#ifdef FW_DOWNLOAD_SPEED
++ u32 tv1, tv2;
++#endif
++
++ ENTER();
++
++ if (!card || !card->func) {
++ PRINTM(ERROR, "sbi_prog_helper(): card or function is NULL!\n");
++ goto done;
++ }
++
++ if (priv->fw_helper) {
++ helper = (u8 *) priv->fw_helper->data;
++ helperlen = priv->fw_helper->size;
++ } else {
++ PRINTM(MSG, "No helper image found! Terminating download.\n");
++ LEAVE();
++ return UAP_STATUS_FAILURE;
++ }
++
++ PRINTM(INFO, "Downloading helper image (%d bytes), block size %d bytes\n",
++ helperlen, SD_BLOCK_SIZE);
++
++#ifdef FW_DOWNLOAD_SPEED
++ tv1 = get_utimeofday();
++#endif
++
++#ifdef PXA3XX_DMA_ALIGN
++ tmphlprbufsz = ALIGN_SZ(UAP_UPLD_SIZE, PXA3XX_DMA_ALIGNMENT);
++#else /* !PXA3XX_DMA_ALIGN */
++ tmphlprbufsz = UAP_UPLD_SIZE;
++#endif /* !PXA3XX_DMA_ALIGN */
++ tmphlprbuf = kmalloc(tmphlprbufsz, GFP_KERNEL);
++ if (!tmphlprbuf) {
++ PRINTM(ERROR,
++ "Unable to allocate buffer for helper. Terminating download\n");
++ ret = UAP_STATUS_FAILURE;
++ goto done;
++ }
++ memset(tmphlprbuf, 0, tmphlprbufsz);
++#ifdef PXA3XX_DMA_ALIGN
++ hlprbuf = (u8 *) ALIGN_ADDR(tmphlprbuf, PXA3XX_DMA_ALIGNMENT);
++#else /* !PXA3XX_DMA_ALIGN */
++ hlprbuf = (u8 *) tmphlprbuf;
++#endif /* !PXA3XX_DMA_ALIGN */
++
++ sdio_claim_host(card->func);
++
++ /* Perform helper data transfer */
++ tx_len = (FIRMWARE_TRANSFER_NBLOCK * SD_BLOCK_SIZE) - INTF_HEADER_LEN;
++ hlprblknow = 0;
++ do {
++ /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits */
++ ret = mv_sdio_poll_card_status(priv, CARD_IO_READY | DN_LD_CARD_RDY);
++ if (ret < 0) {
++ PRINTM(FATAL, "Helper download poll status timeout @ %d\n",
++ hlprblknow);
++ goto done;
++ }
++
++ /* More data? */
++ if (hlprblknow >= helperlen)
++ break;
++
++ /* Set blocksize to transfer - checking for last block */
++ if (helperlen - hlprblknow < tx_len)
++ tx_len = helperlen - hlprblknow;
++
++ /* Set length to the 4-byte header */
++ *(u32 *) hlprbuf = uap_cpu_to_le32(tx_len);
++
++ /* Copy payload to buffer */
++ memcpy(&hlprbuf[INTF_HEADER_LEN], &helper[hlprblknow], tx_len);
++
++ PRINTM(INFO, ".");
++
++ /* Send data */
++ ret = sdio_writesb(card->func, priv->uap_dev.ioport,
++ hlprbuf, FIRMWARE_TRANSFER_NBLOCK * SD_BLOCK_SIZE);
++
++ if (ret < 0) {
++ PRINTM(FATAL, "IO error during helper download @ %d\n", hlprblknow);
++ goto done;
++ }
++
++ hlprblknow += tx_len;
++ } while (TRUE);
++
++#ifdef FW_DOWNLOAD_SPEED
++ tv2 = get_utimeofday();
++ PRINTM(INFO, "helper: %ld.%03ld.%03ld ", tv1 / 1000000,
++ (tv1 % 1000000) / 1000, tv1 % 1000);
++ PRINTM(INFO, " -> %ld.%03ld.%03ld ", tv2 / 1000000, (tv2 % 1000000) / 1000,
++ tv2 % 1000);
++ tv2 -= tv1;
++ PRINTM(INFO, " == %ld.%03ld.%03ld\n", tv2 / 1000000, (tv2 % 1000000) / 1000,
++ tv2 % 1000);
++#endif
++
++ /* Write last EOF data */
++ PRINTM(INFO, "\nTransferring helper image EOF block\n");
++ memset(hlprbuf, 0x0, SD_BLOCK_SIZE);
++ ret = sdio_writesb(card->func, priv->uap_dev.ioport,
++ hlprbuf, SD_BLOCK_SIZE);
++
++ if (ret < 0) {
++ PRINTM(FATAL, "IO error in writing helper image EOF block\n");
++ goto done;
++ }
++
++ ret = UAP_STATUS_SUCCESS;
++
++ done:
++ sdio_release_host(card->func);
++ if (tmphlprbuf)
++ kfree(tmphlprbuf);
++
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function downloads firmware image to the card.
++ *
++ * @param priv A pointer to uap_private structure
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++int
++sbi_prog_fw_w_helper(uap_private * priv)
++{
++ struct sdio_mmc_card *card = priv->uap_dev.card;
++ u8 *firmware = NULL;
++ int firmwarelen;
++ u8 base0;
++ u8 base1;
++ int ret = UAP_STATUS_SUCCESS;
++ int offset;
++ void *tmpfwbuf = NULL;
++ int tmpfwbufsz;
++ u8 *fwbuf;
++ u16 len;
++ int txlen = 0;
++ int tx_blocks = 0;
++ int i = 0;
++ int tries = 0;
++#ifdef FW_DOWNLOAD_SPEED
++ u32 tv1, tv2;
++#endif
++
++ ENTER();
++
++ if (!card || !card->func) {
++ PRINTM(ERROR, "sbi_prog_fw_w_helper(): card or function is NULL!\n");
++ goto done;
++ }
++
++ if (priv->firmware) {
++ firmware = (u8 *) priv->firmware->data;
++ firmwarelen = priv->firmware->size;
++ } else {
++ PRINTM(MSG, "No firmware image found! Terminating download.\n");
++ LEAVE();
++ return UAP_STATUS_FAILURE;
++ }
++
++ PRINTM(INFO, "Downloading FW image (%d bytes)\n", firmwarelen);
++
++#ifdef FW_DOWNLOAD_SPEED
++ tv1 = get_utimeofday();
++#endif
++
++#ifdef PXA3XX_DMA_ALIGN
++ tmpfwbufsz = ALIGN_SZ(UAP_UPLD_SIZE, PXA3XX_DMA_ALIGNMENT);
++#else /* PXA3XX_DMA_ALIGN */
++ tmpfwbufsz = UAP_UPLD_SIZE;
++#endif /* PXA3XX_DMA_ALIGN */
++ tmpfwbuf = kmalloc(tmpfwbufsz, GFP_KERNEL);
++ if (!tmpfwbuf) {
++ PRINTM(ERROR,
++ "Unable to allocate buffer for firmware. Terminating download.\n");
++ ret = UAP_STATUS_FAILURE;
++ goto done;
++ }
++ memset(tmpfwbuf, 0, tmpfwbufsz);
++#ifdef PXA3XX_DMA_ALIGN
++ /* Ensure 8-byte aligned firmware buffer */
++ fwbuf = (u8 *) ALIGN_ADDR(tmpfwbuf, PXA3XX_DMA_ALIGNMENT);
++#else /* PXA3XX_DMA_ALIGN */
++ fwbuf = (u8 *) tmpfwbuf;
++#endif /* PXA3XX_DMA_ALIGN */
++
++ sdio_claim_host(card->func);
++
++ /* Perform firmware data transfer */
++ offset = 0;
++ do {
++ /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits */
++ ret = mv_sdio_poll_card_status(priv, CARD_IO_READY | DN_LD_CARD_RDY);
++ if (ret < 0) {
++ PRINTM(FATAL, "FW download with helper poll status timeout @ %d\n",
++ offset);
++ goto done;
++ }
++
++ /* More data? */
++ if (offset >= firmwarelen)
++ break;
++
++ for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
++ if ((ret = sbi_read_ioreg(priv, HOST_F1_RD_BASE_0, &base0)) < 0) {
++ PRINTM(WARN, "Dev BASE0 register read failed:"
++ " base0=0x%04X(%d). Terminating download.\n", base0,
++ base0);
++ ret = UAP_STATUS_FAILURE;
++ goto done;
++ }
++ if ((ret = sbi_read_ioreg(priv, HOST_F1_RD_BASE_1, &base1)) < 0) {
++ PRINTM(WARN, "Dev BASE1 register read failed:"
++ " base1=0x%04X(%d). Terminating download.\n", base1,
++ base1);
++ ret = UAP_STATUS_FAILURE;
++ goto done;
++ }
++ len = (((u16) base1) << 8) | base0;
++
++ /* For SD8688 wait until the length is not 0, 1 or 2 before
++ downloading the first FW block, since BOOT code writes the
++ register to indicate the helper/FW download winner, the value
++ could be 1 or 2 (Func1 or Func2). */
++ if ((len && offset) || (len > 2))
++ break;
++ udelay(10);
++ }
++
++ if (len == 0)
++ break;
++ else if (len > UAP_UPLD_SIZE) {
++ PRINTM(FATAL, "FW download failure @ %d, invalid length %d\n",
++ offset, len);
++ ret = UAP_STATUS_FAILURE;
++ goto done;
++ }
++
++ txlen = len;
++
++ if (len & BIT(0)) {
++ i++;
++ if (i > MAX_WRITE_IOMEM_RETRY) {
++ PRINTM(FATAL,
++ "FW download failure @ %d, over max retry count\n",
++ offset);
++ ret = UAP_STATUS_FAILURE;
++ goto done;
++ }
++ PRINTM(ERROR, "FW CRC error indicated by the helper:"
++ " len = 0x%04X, txlen = %d\n", len, txlen);
++ len &= ~BIT(0);
++ /* Setting this to 0 to resend from same offset */
++ txlen = 0;
++ } else {
++ i = 0;
++
++ /* Set blocksize to transfer - checking for last block */
++ if (firmwarelen - offset < txlen) {
++ txlen = firmwarelen - offset;
++ }
++ PRINTM(INFO, ".");
++
++ tx_blocks = (txlen + SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE;
++
++ /* Copy payload to buffer */
++ memcpy(fwbuf, &firmware[offset], txlen);
++ }
++
++ /* Send data */
++ ret = sdio_writesb(card->func, priv->uap_dev.ioport,
++ fwbuf, tx_blocks * SD_BLOCK_SIZE);
++
++ if (ret < 0) {
++ PRINTM(ERROR, "FW download, write iomem (%d) failed @ %d\n", i,
++ offset);
++ if (sbi_write_ioreg(priv, CONFIGURATION_REG, 0x04) < 0) {
++ PRINTM(ERROR, "write ioreg failed (CFG)\n");
++ }
++ }
++
++ offset += txlen;
++ } while (TRUE);
++
++ PRINTM(INFO, "\nFW download over, size %d bytes\n", offset);
++
++ ret = UAP_STATUS_SUCCESS;
++ done:
++#ifdef FW_DOWNLOAD_SPEED
++ tv2 = get_utimeofday();
++ PRINTM(INFO, "FW: %ld.%03ld.%03ld ", tv1 / 1000000,
++ (tv1 % 1000000) / 1000, tv1 % 1000);
++ PRINTM(INFO, " -> %ld.%03ld.%03ld ", tv2 / 1000000,
++ (tv2 % 1000000) / 1000, tv2 % 1000);
++ tv2 -= tv1;
++ PRINTM(INFO, " == %ld.%03ld.%03ld\n", tv2 / 1000000,
++ (tv2 % 1000000) / 1000, tv2 % 1000);
++#endif
++ sdio_release_host(card->func);
++ if (tmpfwbuf)
++ kfree(tmpfwbuf);
++
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function checks if the firmware is ready to accept
++ * command or not.
++ *
++ * @param priv A pointer to uap_private structure
++ * @param pollnum Poll number
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++int
++sbi_check_fw_status(uap_private * priv, int pollnum)
++{
++ struct sdio_mmc_card *card = priv->uap_dev.card;
++ int ret = UAP_STATUS_SUCCESS;
++ u16 firmwarestat;
++ int tries;
++
++ ENTER();
++
++ sdio_claim_host(card->func);
++
++ /* Wait for firmware initialization event */
++ for (tries = 0; tries < pollnum; tries++) {
++ if ((ret = sd_read_firmware_status(priv, &firmwarestat)) < 0)
++ continue;
++ if (firmwarestat == FIRMWARE_READY) {
++ ret = UAP_STATUS_SUCCESS;
++ break;
++ } else {
++ mdelay(10);
++ ret = UAP_STATUS_FAILURE;
++ }
++ }
++
++ if (ret < 0)
++ goto done;
++
++ ret = UAP_STATUS_SUCCESS;
++ sd_get_rx_unit(priv);
++
++ done:
++ sdio_release_host(card->func);
++
++ LEAVE();
++ return ret;
++}
++
++/**
++ * @brief This function set bus clock on/off
++ *
++ * @param priv A pointer to uap_private structure
++ * @param option TRUE--on , FALSE--off
++ * @return UAP_STATUS_SUCCESS
++ */
++#if 0
++static int
++sbi_set_bus_clock(uap_private * priv, u8 option)
++{
++ ENTER();
++ LEAVE();
++ return UAP_STATUS_SUCCESS;
++}
++#endif
++
++/**
++ * @brief This function wakeup firmware
++ *
++ * @param priv A pointer to uap_private structure
++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
++ */
++int
++sbi_wakeup_firmware(uap_private * priv)
++{
++ struct sdio_mmc_card *card = priv->uap_dev.card;
++ int ret = UAP_STATUS_SUCCESS;
++
++ ENTER();
++
++ if (!card || !card->func) {
++ PRINTM(ERROR, "card or function is NULL!\n");
++ LEAVE();
++ return UAP_STATUS_FAILURE;
++ }
++ sdio_claim_host(card->func);
++ sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret);
++ sdio_release_host(card->func);
++ LEAVE();
++ return ret;
++}
+diff --git a/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h b/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h
+new file mode 100644
+index 0000000..191c67f
+--- /dev/null
++++ b/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h
+@@ -0,0 +1,136 @@
++/** @file uap_sdio_mmc.h
++ * @brief This file contains SDIO IF (interface) module
++ * related macros, enum, and structure.
++ *
++ * Copyright (C) 2007-2009, Marvell International Ltd.
++ *
++ * This software file (the "File") is distributed by Marvell International
++ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
++ * (the "License"). You may use, redistribute and/or modify this File in
++ * accordance with the terms and conditions of the License, a copy of which
++ * is available along with the File in the gpl.txt file or by writing to
++ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++ *
++ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
++ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
++ * this warranty disclaimer.
++ *
++ */
++/****************************************************
++Change log:
++ 10/10/07: initial version
++****************************************************/
++
++#ifndef _UAP_SDIO_MMC_H
++#define _UAP_SDIO_MMC_H
++
++#include <linux/mmc/sdio.h>
++#include <linux/mmc/sdio_ids.h>
++#include <linux/mmc/sdio_func.h>
++#include <linux/mmc/card.h>
++
++#include "uap_headers.h"
++
++/** The number of times to try when waiting for downloaded firmware to
++ become active. (polling the scratch register). */
++#define MAX_FIRMWARE_POLL_TRIES 100
++
++/** Firmware ready */
++#define FIRMWARE_READY 0xfedc
++
++/** Number of firmware blocks to transfer */
++#define FIRMWARE_TRANSFER_NBLOCK 2
++
++/* Host Control Registers */
++/** Host Control Registers : I/O port 0 */
++#define IO_PORT_0_REG 0x00
++/** Host Control Registers : I/O port 1 */
++#define IO_PORT_1_REG 0x01
++/** Host Control Registers : I/O port 2 */
++#define IO_PORT_2_REG 0x02
++
++/** Host Control Registers : Configuration */
++#define CONFIGURATION_REG 0x03
++/** Host Control Registers : Host without Command 53 finish host */
++#define HOST_WO_CMD53_FINISH_HOST (0x1U << 2)
++/** Host Control Registers : Host power up */
++#define HOST_POWER_UP (0x1U << 1)
++/** Host Control Registers : Host power down */
++#define HOST_POWER_DOWN (0x1U << 0)
++
++/** Host Control Registers : Host interrupt mask */
++#define HOST_INT_MASK_REG 0x04
++/** Host Control Registers : Upload host interrupt mask */
++#define UP_LD_HOST_INT_MASK (0x1U)
++/** Host Control Registers : Download host interrupt mask */
++#define DN_LD_HOST_INT_MASK (0x2U)
++/** Enable Host interrupt mask */
++#define HIM_ENABLE (UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK)
++/** Disable Host interrupt mask */
++#define HIM_DISABLE 0xff
++
++/** Host Control Registers : Host interrupt status */
++#define HOST_INTSTATUS_REG 0x05
++/** Host Control Registers : Upload host interrupt status */
++#define UP_LD_HOST_INT_STATUS (0x1U)
++/** Host Control Registers : Download host interrupt status */
++#define DN_LD_HOST_INT_STATUS (0x2U)
++
++/** Host F1 read base 0 */
++#define HOST_F1_RD_BASE_0 0x10
++/** Host F1 read base 1 */
++#define HOST_F1_RD_BASE_1 0x11
++
++/** Card Control Registers : Card status register */
++#define CARD_STATUS_REG 0x20
++/** Card Control Registers : Card I/O ready */
++#define CARD_IO_READY (0x1U << 3)
++/** Card Control Registers : CIS card ready */
++#define CIS_CARD_RDY (0x1U << 2)
++/** Card Control Registers : Upload card ready */
++#define UP_LD_CARD_RDY (0x1U << 1)
++/** Card Control Registers : Download card ready */
++#define DN_LD_CARD_RDY (0x1U << 0)
++
++/** Card Control Registers : Card OCR 0 register */
++#define CARD_OCR_0_REG 0x34
++/** Card Control Registers : Card OCR 1 register */
++#define CARD_OCR_1_REG 0x35
++
++/** Firmware status 0 register */
++#define CARD_FW_STATUS0_REG 0x40
++/** Firmware status 1 register */
++#define CARD_FW_STATUS1_REG 0x41
++/** Rx length register */
++#define CARD_RX_LEN_REG 0x42
++/** Rx unit register */
++#define CARD_RX_UNIT_REG 0x43
++
++/** Chip Id Register 0 */
++#define CARD_CHIP_ID_0_REG 0x801c
++/** Chip Id Register 1 */
++#define CARD_CHIP_ID_1_REG 0x801d
++
++#ifdef PXA3XX_DMA_ALIGN
++/** DMA alignment value for PXA3XX platforms */
++#define PXA3XX_DMA_ALIGNMENT 8
++/** Macros for Data Alignment : size */
++#define ALIGN_SZ(p, a) \
++ (((p) + ((a) - 1)) & ~((a) - 1))
++
++/** Macros for Data Alignment : address */
++#define ALIGN_ADDR(p, a) \
++ ((((u32)(p)) + (((u32)(a)) - 1)) & ~(((u32)(a)) - 1))
++#endif /* PXA3XX_DMA_ALIGN */
++
++struct sdio_mmc_card
++{
++ /** sdio_func structure pointer */
++ struct sdio_func *func;
++ /** uap_private structure pointer */
++ uap_private *priv;
++};
++
++#endif /* _UAP_SDIO_MMC_H */
--- /dev/null
+diff --git a/minilzo/minilzo.c b/minilzo/minilzo.c
+index 34ce0f0..ecfdf66 100644
+--- a/minilzo/minilzo.c
++++ b/minilzo/minilzo.c
+@@ -3547,6 +3547,8 @@ DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len,
+ #undef TEST_LBO
+ #undef NEED_IP
+ #undef NEED_OP
++#undef TEST_IV
++#undef TEST_OV
+ #undef HAVE_TEST_IP
+ #undef HAVE_TEST_OP
+ #undef HAVE_NEED_IP
+@@ -3561,6 +3563,7 @@ DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len,
+ # if (LZO_TEST_OVERRUN_INPUT >= 2)
+ # define NEED_IP(x) \
+ if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun
++# define TEST_IV(x) if ((x) > (lzo_uint)0 - (511)) goto input_overrun
+ # endif
+ #endif
+
+@@ -3572,6 +3575,7 @@ DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len,
+ # undef TEST_OP
+ # define NEED_OP(x) \
+ if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun
++# define TEST_OV(x) if ((x) > (lzo_uint)0 - (511)) goto output_overrun
+ # endif
+ #endif
+
+@@ -3602,11 +3606,13 @@ DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len,
+ # define HAVE_NEED_IP 1
+ #else
+ # define NEED_IP(x) ((void) 0)
++# define TEST_IV(x) ((void) 0)
+ #endif
+ #if defined(NEED_OP)
+ # define HAVE_NEED_OP 1
+ #else
+ # define NEED_OP(x) ((void) 0)
++# define TEST_OV(x) ((void) 0)
+ #endif
+
+ #if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP)
+@@ -3687,6 +3693,7 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len,
+ {
+ t += 255;
+ ip++;
++ TEST_IV(t);
+ NEED_IP(1);
+ }
+ t += 15 + *ip++;
+@@ -3835,6 +3842,7 @@ match:
+ {
+ t += 255;
+ ip++;
++ TEST_OV(t);
+ NEED_IP(1);
+ }
+ t += 31 + *ip++;
+@@ -3879,6 +3887,7 @@ match:
+ {
+ t += 255;
+ ip++;
++ TEST_OV(t);
+ NEED_IP(1);
+ }
+ t += 7 + *ip++;
+@@ -4073,6 +4082,8 @@ lookbehind_overrun:
+ #undef TEST_LBO
+ #undef NEED_IP
+ #undef NEED_OP
++#undef TEST_IV
++#undef TEST_OV
+ #undef HAVE_TEST_IP
+ #undef HAVE_TEST_OP
+ #undef HAVE_NEED_IP
+@@ -4087,6 +4098,7 @@ lookbehind_overrun:
+ # if (LZO_TEST_OVERRUN_INPUT >= 2)
+ # define NEED_IP(x) \
+ if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun
++# define TEST_IV(x) if ((x) > (lzo_uint)0 - (511)) goto input_overrun
+ # endif
+ #endif
+
+@@ -4098,6 +4110,7 @@ lookbehind_overrun:
+ # undef TEST_OP
+ # define NEED_OP(x) \
+ if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun
++# define TEST_OV(x) if ((x) > (lzo_uint)0 - (511)) goto output_overrun
+ # endif
+ #endif
+
+@@ -4128,11 +4141,13 @@ lookbehind_overrun:
+ # define HAVE_NEED_IP 1
+ #else
+ # define NEED_IP(x) ((void) 0)
++# define TEST_IV(x) ((void) 0)
+ #endif
+ #if defined(NEED_OP)
+ # define HAVE_NEED_OP 1
+ #else
+ # define NEED_OP(x) ((void) 0)
++# define TEST_OV(x) ((void) 0)
+ #endif
+
+ #if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP)
+@@ -4213,6 +4228,7 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len,
+ {
+ t += 255;
+ ip++;
++ TEST_IV(t);
+ NEED_IP(1);
+ }
+ t += 15 + *ip++;
+@@ -4361,6 +4377,7 @@ match:
+ {
+ t += 255;
+ ip++;
++ TEST_OV(t);
+ NEED_IP(1);
+ }
+ t += 31 + *ip++;
+@@ -4405,6 +4422,7 @@ match:
+ {
+ t += 255;
+ ip++;
++ TEST_OV(t);
+ NEED_IP(1);
+ }
+ t += 7 + *ip++;
+diff --git a/src/lzo1_d.ch b/src/lzo1_d.ch
+index 40a5bfd..c442d9c 100644
+--- a/src/lzo1_d.ch
++++ b/src/lzo1_d.ch
+@@ -76,6 +76,8 @@
+ #undef TEST_LBO
+ #undef NEED_IP
+ #undef NEED_OP
++#undef TEST_IV
++#undef TEST_OV
+ #undef HAVE_TEST_IP
+ #undef HAVE_TEST_OP
+ #undef HAVE_NEED_IP
+@@ -91,6 +93,7 @@
+ # if (LZO_TEST_OVERRUN_INPUT >= 2)
+ # define NEED_IP(x) \
+ if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun
++# define TEST_IV(x) if ((x) > (lzo_uint)0 - (511)) goto input_overrun
+ # endif
+ #endif
+
+@@ -102,6 +105,7 @@
+ # undef TEST_OP /* don't need both of the tests here */
+ # define NEED_OP(x) \
+ if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun
++# define TEST_OV(x) if ((x) > (lzo_uint)0 - (511)) goto output_overrun
+ # endif
+ #endif
+
+@@ -135,11 +139,13 @@
+ # define HAVE_NEED_IP 1
+ #else
+ # define NEED_IP(x) ((void) 0)
++# define TEST_IV(x) ((void) 0)
+ #endif
+ #if defined(NEED_OP)
+ # define HAVE_NEED_OP 1
+ #else
+ # define NEED_OP(x) ((void) 0)
++# define TEST_OV(x) ((void) 0)
+ #endif
+
+
+diff --git a/src/lzo1b_d.ch b/src/lzo1b_d.ch
+index fe5f361..36b4b6b 100644
+--- a/src/lzo1b_d.ch
++++ b/src/lzo1b_d.ch
+@@ -187,6 +187,7 @@ match:
+ {
+ t += 255;
+ ip++;
++ TEST_OV(t);
+ NEED_IP(1);
+ }
+ t += (M4_MIN_LEN - M3_MIN_LEN) + *ip++;
+diff --git a/src/lzo1f_d.ch b/src/lzo1f_d.ch
+index 9e942f5..0c2199e 100644
+--- a/src/lzo1f_d.ch
++++ b/src/lzo1f_d.ch
+@@ -84,6 +84,7 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len,
+ {
+ t += 255;
+ ip++;
++ TEST_IV(t);
+ NEED_IP(1);
+ }
+ t += 31 + *ip++;
+@@ -138,6 +139,7 @@ match:
+ {
+ t += 255;
+ ip++;
++ TEST_OV(t);
+ NEED_IP(1);
+ }
+ t += 31 + *ip++;
+diff --git a/src/lzo1x_d.ch b/src/lzo1x_d.ch
+index 49cf326..c804cc7 100644
+--- a/src/lzo1x_d.ch
++++ b/src/lzo1x_d.ch
+@@ -120,6 +120,7 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len,
+ {
+ t += 255;
+ ip++;
++ TEST_IV(t);
+ NEED_IP(1);
+ }
+ t += 15 + *ip++;
+@@ -273,6 +274,7 @@ match:
+ {
+ t += 255;
+ ip++;
++ TEST_OV(t);
+ NEED_IP(1);
+ }
+ t += 31 + *ip++;
+@@ -317,6 +319,7 @@ match:
+ {
+ t += 255;
+ ip++;
++ TEST_OV(t);
+ NEED_IP(1);
+ }
+ t += 7 + *ip++;
+diff --git a/src/lzo2a_d.ch b/src/lzo2a_d.ch
+index 48e51ca..954f07e 100644
+--- a/src/lzo2a_d.ch
++++ b/src/lzo2a_d.ch
+@@ -131,6 +131,7 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len,
+ {
+ t += 255;
+ ip++;
++ TEST_OV(t);
+ NEED_IP(1);
+ }
+ t += *ip++;
--- /dev/null
+The getline function used in a couple of places in netpbm-free is also
+defined by POSIX:2008, and so netpbm-free fails to build with newer
+versions of (e)glibc. Here's a patch to rename it.
+
+ * Rename getline functions to get_line to avoid conflict with POSIX:2008.
+
+--- netpbm-free-10.0.orig/ppm/xvminitoppm.c
++++ netpbm-free-10.0/ppm/xvminitoppm.c
+@@ -14,7 +14,7 @@
+ #include "ppm.h"
+ #define BUFSIZE 256
+
+-static void getline ARGS((FILE *fp, char *buf));
++static void get_line ARGS((FILE *fp, char *buf));
+
+ int
+ main(argc, argv)
+@@ -48,18 +48,18 @@
+ i++;
+ }
+
+- getline(ifp, buf);
++ get_line(ifp, buf);
+ if( strncmp(buf, "P7 332", 6) != 0 )
+ pm_error("bad magic number - not a XV thumbnail picture");
+
+ while(1) {
+- getline(ifp, buf);
++ get_line(ifp, buf);
+ if( strncmp(buf, "#END_OF_COMMENTS", 16)==0 )
+ break;
+ if( strncmp(buf, "#BUILTIN", 8)==0 )
+ pm_error("cannot convert builtin XV thumbnail pictures");
+ }
+- getline(ifp, buf);
++ get_line(ifp, buf);
+ if( sscanf(buf, "%d %d %d", &cols, &rows, &maxval) != 3 )
+ pm_error("error parsing dimension info");
+ if( maxval != 255 )
+@@ -85,7 +85,7 @@
+
+
+ static void
+-getline(fp, buf)
++get_line(fp, buf)
+ FILE *fp;
+ char *buf;
+ {
+--- netpbm-free-10.0.orig/ppm/xpmtoppm.c
++++ netpbm-free-10.0/ppm/xpmtoppm.c
+@@ -114,7 +114,7 @@
+
+
+ static void
+-getline(char * const line, int const size, FILE * const stream) {
++get_line(char * const line, int const size, FILE * const stream) {
+ /*----------------------------------------------------------------------------
+ Read the next line from the input file 'stream', through the one-line
+ buffer lastInputLine[].
+@@ -130,7 +130,7 @@
+ Exit program if the line doesn't fit in the buffer.
+ -----------------------------------------------------------------------------*/
+ if (size > MAX_LINE+1)
+- pm_error("INTERNAL ERROR: getline() received 'size' parameter "
++ pm_error("INTERNAL ERROR: get_line() received 'size' parameter "
+ "which is out of bounds");
+
+ if (backup) {
+@@ -346,7 +346,7 @@
+ int * const transparentP) {
+ /*----------------------------------------------------------------------------
+ Read the header of the XPM file on stream 'stream'. Assume the
+- getline() stream is presently positioned to the beginning of the
++ get_line() stream is presently positioned to the beginning of the
+ file and it is a Version 3 XPM file. Leave the stream positioned
+ after the header.
+
+@@ -377,25 +377,25 @@
+ *widthP = *heightP = *ncolorsP = *chars_per_pixelP = -1;
+
+ /* Read the XPM signature comment */
+- getline(line, sizeof(line), stream);
++ get_line(line, sizeof(line), stream);
+ if (strncmp(line, xpm3_signature, strlen(xpm3_signature)) != 0)
+ pm_error("Apparent XPM 3 file does not start with '/* XPM */'. "
+ "First line is '%s'", xpm3_signature);
+
+ /* Read the assignment line */
+- getline(line, sizeof(line), stream);
++ get_line(line, sizeof(line), stream);
+ if (strncmp(line, "static char", 11) != 0)
+ pm_error("Cannot find data structure declaration. Expected a "
+ "line starting with 'static char', but found the line "
+ "'%s'.", line);
+
+ /* Read the hints line */
+- getline(line, sizeof(line), stream);
++ get_line(line, sizeof(line), stream);
+ /* skip the comment line if any */
+ if (!strncmp(line, "/*", 2)) {
+ while (!strstr(line, "*/"))
+- getline(line, sizeof(line), stream);
+- getline(line, sizeof(line), stream);
++ get_line(line, sizeof(line), stream);
++ get_line(line, sizeof(line), stream);
+ }
+ if (sscanf(line, "\"%d %d %d %d\",", widthP, heightP,
+ ncolorsP, chars_per_pixelP) != 4)
+@@ -427,10 +427,10 @@
+ *transparentP = -1; /* initial value */
+
+ for (seqNum = 0; seqNum < *ncolorsP; seqNum++) {
+- getline(line, sizeof(line), stream);
++ get_line(line, sizeof(line), stream);
+ /* skip the comment line if any */
+ if (!strncmp(line, "/*", 2))
+- getline(line, sizeof(line), stream);
++ get_line(line, sizeof(line), stream);
+
+ interpretXpm3ColorTableLine(line, seqNum, *chars_per_pixelP,
+ *colorsP, *ptabP, transparentP);
+@@ -445,7 +445,7 @@
+ pixel ** const colorsP, int ** const ptabP) {
+ /*----------------------------------------------------------------------------
+ Read the header of the XPM file on stream 'stream'. Assume the
+- getline() stream is presently positioned to the beginning of the
++ get_line() stream is presently positioned to the beginning of the
+ file and it is a Version 1 XPM file. Leave the stream positioned
+ after the header.
+
+@@ -464,7 +464,7 @@
+ /* Read the initial defines. */
+ processedStaticChar = FALSE;
+ while (!processedStaticChar) {
+- getline(line, sizeof(line), stream);
++ get_line(line, sizeof(line), stream);
+
+ if (sscanf(line, "#define %s %d", str1, &v) == 2) {
+ char *t1;
+@@ -512,7 +512,7 @@
+ /* If there's a monochrome color table, skip it. */
+ if (!strncmp(t1, "mono", 4)) {
+ for (;;) {
+- getline(line, sizeof(line), stream);
++ get_line(line, sizeof(line), stream);
+ if (!strncmp(line, "static char", 11))
+ break;
+ }
+@@ -533,7 +533,7 @@
+
+ /* Read color table. */
+ for (i = 0; i < *ncolorsP; ++i) {
+- getline(line, sizeof(line), stream);
++ get_line(line, sizeof(line), stream);
+
+ if ((t1 = strchr(line, '"')) == NULL)
+ pm_error("D error scanning color table");
+@@ -569,7 +569,7 @@
+ "static char ...").
+ */
+ for (;;) {
+- getline(line, sizeof(line), stream);
++ get_line(line, sizeof(line), stream);
+ if (strncmp(line, "static char", 11) == 0)
+ break;
+ }
+@@ -660,7 +660,7 @@
+ backup = FALSE;
+
+ /* Read the header line */
+- getline(line, sizeof(line), stream);
++ get_line(line, sizeof(line), stream);
+ backup = TRUE; /* back up so next read reads this line again */
+
+ rc = sscanf(line, "/* %s */", str1);
+@@ -681,7 +681,7 @@
+ pm_error("Could not get %d bytes of memory for image", totalpixels);
+ cursor = *dataP;
+ maxcursor = *dataP + totalpixels - 1;
+- getline(line, sizeof(line), stream);
++ get_line(line, sizeof(line), stream);
+ /* read next line (first line may not always start with comment) */
+ while (cursor <= maxcursor) {
+ if (strncmp(line, "/*", 2) == 0) {
+@@ -691,7 +691,7 @@
+ ncolors, ptab, &cursor, maxcursor);
+ }
+ if (cursor <= maxcursor)
+- getline(line, sizeof(line), stream);
++ get_line(line, sizeof(line), stream);
+ }
+ if (ptab) free(ptab);
+ }
+
+Thanks,
+
+--
+Colin Watson [cjwatson@ubuntu.com]
+
+
+
+
--- /dev/null
+diff -up openssl-1.0.0-beta5/Configure.enginesdir openssl-1.0.0-beta5/Configure
+--- openssl-1.0.0-beta5/Configure.enginesdir 2010-01-20 18:07:05.000000000 +0100
++++ openssl-1.0.0-beta5/Configure 2010-01-20 18:10:48.000000000 +0100
+@@ -622,6 +622,7 @@ my $idx_multilib = $idx++;
+ my $prefix="";
+ my $libdir="";
+ my $openssldir="";
++my $enginesdir="";
+ my $exe_ext="";
+ my $install_prefix= "$ENV{'INSTALL_PREFIX'}";
+ my $cross_compile_prefix="";
+@@ -833,6 +834,10 @@ PROCESS_ARGS:
+ {
+ $openssldir=$1;
+ }
++ elsif (/^--enginesdir=(.*)$/)
++ {
++ $enginesdir=$1;
++ }
+ elsif (/^--install.prefix=(.*)$/)
+ {
+ $install_prefix=$1;
+@@ -1053,7 +1058,7 @@ chop $prefix if $prefix =~ /.\/$/;
+
+ $openssldir=$prefix . "/ssl" if $openssldir eq "";
+ $openssldir=$prefix . "/" . $openssldir if $openssldir !~ /(^\/|^[a-zA-Z]:[\\\/])/;
+-
++$enginesdir="$prefix/lib/engines" if $enginesdir eq "";
+
+ print "IsMK1MF=$IsMK1MF\n";
+
+@@ -1673,7 +1678,7 @@ while (<IN>)
+ }
+ elsif (/^#define\s+ENGINESDIR/)
+ {
+- my $foo = "$prefix/$libdir/engines";
++ my $foo = "$enginesdir";
+ $foo =~ s/\\/\\\\/g;
+ print OUT "#define ENGINESDIR \"$foo\"\n";
+ }
+diff -up openssl-1.0.0-beta5/engines/Makefile.enginesdir openssl-1.0.0-beta5/engines/Makefile
+--- openssl-1.0.0-beta5/engines/Makefile.enginesdir 2010-01-16 21:06:09.000000000 +0100
++++ openssl-1.0.0-beta5/engines/Makefile 2010-01-20 18:07:05.000000000 +0100
+@@ -124,7 +124,7 @@ install:
+ sfx=".so"; \
+ cp cyg$$l.dll $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/engines/$$pfx$$l$$sfx.new; \
+ fi; \
+- chmod 555 $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/engines/$$pfx$$l$$sfx.new; \
++ chmod 755 $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/engines/$$pfx$$l$$sfx.new; \
+ mv -f $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/engines/$$pfx$$l$$sfx.new $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/engines/$$pfx$$l$$sfx ); \
+ done; \
+ fi
--- /dev/null
+diff -up openssl-1.0.2e/Configure.rpmbuild openssl-1.0.2e/Configure
+--- openssl-1.0.2e/Configure.rpmbuild 2015-12-03 15:04:23.000000000 +0100
++++ openssl-1.0.2e/Configure 2015-12-04 13:20:22.996835604 +0100
+@@ -365,8 +365,8 @@ my %table=(
+ ####
+ # *-generic* is endian-neutral target, but ./config is free to
+ # throw in -D[BL]_ENDIAN, whichever appropriate...
+-"linux-generic32","gcc:-O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+-"linux-ppc", "gcc:-DB_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL:${ppc32_asm}:linux32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-generic32","gcc:-Wall \$(RPM_OPT_FLAGS)::-D_REENTRANT::-Wl,-z,relro -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC:\$(RPM_OPT_FLAGS):.so.\$(SHLIB_SONAMEVER)",
++"linux-ppc", "gcc:-DB_ENDIAN -Wall \$(RPM_OPT_FLAGS)::-D_REENTRANT::-Wl,-z,relro -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL:${ppc32_asm}:linux32:dlfcn:linux-shared:-fPIC:\$(RPM_OPT_FLAGS):.so.\$(SHLIB_SONAMEVER)",
+
+ #######################################################################
+ # Note that -march is not among compiler options in below linux-armv4
+@@ -395,31 +395,31 @@ my %table=(
+ #
+ # ./Configure linux-armv4 -march=armv6 -D__ARM_MAX_ARCH__=8
+ #
+-"linux-armv4", "gcc: -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+-"linux-aarch64","gcc: -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${aarch64_asm}:linux64:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-armv4", "gcc:-Wall \$(RPM_OPT_FLAGS)::-D_REENTRANT::-Wl,-z,relro -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC:\$(RPM_OPT_FLAGS):.so.\$(SHLIB_SONAMEVER)",
++"linux-aarch64","gcc:-DL_ENDIAN -Wall \$(RPM_OPT_FLAGS)::-D_REENTRANT::-Wl,-z,relro -ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${aarch64_asm}:linux64:dlfcn:linux-shared:-fPIC:\$(RPM_OPT_FLAGS):.so.\$(SHLIB_SONAMEVER):::64",
+ # Configure script adds minimally required -march for assembly support,
+ # if no -march was specified at command line. mips32 and mips64 below
+ # refer to contemporary MIPS Architecture specifications, MIPS32 and
+ # MIPS64, rather than to kernel bitness.
+-"linux-mips32", "gcc:-mabi=32 -O3 -Wall -DBN_DIV3W::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+-"linux-mips64", "gcc:-mabi=n32 -O3 -Wall -DBN_DIV3W::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips64_asm}:n32:dlfcn:linux-shared:-fPIC:-mabi=n32:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::32",
+-"linux64-mips64", "gcc:-mabi=64 -O3 -Wall -DBN_DIV3W::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips64_asm}:64:dlfcn:linux-shared:-fPIC:-mabi=64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
++"linux-mips32", "gcc:-mabi=32 -Wall \$(RPM_OPT_FLAGS) -DBN_DIV3W::-D_REENTRANT::-Wl,-z,relro -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC:\$(RPM_OPT_FLAGS):.so.\$(SHLIB_SONAMEVER)",
++"linux-mips64", "gcc:-mabi=n32 -Wall \$(RPM_OPT_FLAGS) -DBN_DIV3W::-D_REENTRANT::-Wl,-z,relro -ldl:SIXTY_FOUR_BIT RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips64_asm}:n32:dlfcn:linux-shared:-fPIC:-mabi=n32 \$(RPM_OPT_FLAGS):.so.\$(SHLIB_SONAMEVER):::32",
++"linux64-mips64", "gcc:-mabi=64 -Wall \$(RPM_OPT_FLAGS) -DBN_DIV3W::-D_REENTRANT::-Wl,-z,relro -ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips64_asm}:64:dlfcn:linux-shared:-fPIC:-mabi=64 \$(RPM_OPT_FLAGS):.so.\$(SHLIB_SONAMEVER):::64",
+ #### IA-32 targets...
+ "linux-ia32-icc", "icc:-DL_ENDIAN -O2::-D_REENTRANT::-ldl -no_cpprt:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-KPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+-"linux-elf", "gcc:-DL_ENDIAN -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-elf", "gcc:-DL_ENDIAN -Wall \$(RPM_OPT_FLAGS)::-D_REENTRANT::-Wl,-z,relro -ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC:\$(RPM_OPT_FLAGS):.so.\$(SHLIB_SONAMEVER)",
+ "linux-aout", "gcc:-DL_ENDIAN -O3 -fomit-frame-pointer -march=i486 -Wall::(unknown):::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_asm}:a.out",
+ ####
+-"linux-generic64","gcc:-O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+-"linux-ppc64", "gcc:-m64 -DB_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL:${ppc64_asm}:linux64:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
+-"linux-ppc64le","gcc:-m64 -DL_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL:$ppc64_asm:linux64le:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::",
+-"linux-ia64", "gcc:-DL_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_UNROLL DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-generic64","gcc:-Wall \$(RPM_OPT_FLAGS)::-D_REENTRANT::-Wl,-z,relro -ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC:\$(RPM_OPT_FLAGS):.so.\$(SHLIB_SONAMEVER):::64",
++"linux-ppc64", "gcc:-m64 -DB_ENDIAN -Wall \$(RPM_OPT_FLAGS)::-D_REENTRANT::-Wl,-z,relro -ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL:${ppc64_asm}:linux64:dlfcn:linux-shared:-fPIC:-m64 \$(RPM_OPT_FLAGS):.so.\$(SHLIB_SONAMEVER):::64",
++"linux-ppc64le","gcc:-m64 -DL_ENDIAN -Wall \$(RPM_OPT_FLAGS)::-D_REENTRANT::-Wl,-z,relro -ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL:$ppc64_asm:linux64le:dlfcn:linux-shared:-fPIC:-m64 \$(RPM_OPT_FLAGS):.so.\$(SHLIB_SONAMEVER):::64",
++"linux-ia64", "gcc:-DL_ENDIAN -Wall \$(RPM_OPT_FLAGS)::-D_REENTRANT::-Wl,-z,relro -ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_UNROLL DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC:\$(RPM_OPT_FLAGS):.so.\$(SHLIB_SONAMEVER)",
+ "linux-ia64-icc","icc:-DL_ENDIAN -O2 -Wall::-D_REENTRANT::-ldl -no_cpprt:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_RISC1 DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
+-"linux-x86_64", "gcc:-m64 -DL_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
++"linux-x86_64", "gcc:-m64 -DL_ENDIAN -Wall \$(RPM_OPT_FLAGS)::-D_REENTRANT::-Wl,-z,relro -ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64 \$(RPM_OPT_FLAGS):.so.\$(SHLIB_SONAMEVER):::64",
+ "linux-x86_64-clang", "clang: -m64 -DL_ENDIAN -O3 -Wall -Wextra $clang_disabled_warnings -Qunused-arguments::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
+ "debug-linux-x86_64-clang", "clang: -DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG -m64 -DL_ENDIAN -g -Wall -Wextra $clang_disabled_warnings -Qunused-arguments::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
+ "linux-x86_64-icc", "icc:-DL_ENDIAN -O2::-D_REENTRANT::-ldl -no_cpprt:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
+ "linux-x32", "gcc:-mx32 -DL_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT RC4_CHUNK_LL DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-mx32:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::x32",
+-"linux64-s390x", "gcc:-m64 -DB_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL:${s390x_asm}:64:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
++"linux64-s390x", "gcc:-m64 -DB_ENDIAN -Wall \$(RPM_OPT_FLAGS)::-D_REENTRANT::-Wl,-z,relro -ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL:${s390x_asm}:64:dlfcn:linux-shared:-fPIC:-m64 \$(RPM_OPT_FLAGS):.so.\$(SHLIB_SONAMEVER):::64",
+ #### So called "highgprs" target for z/Architecture CPUs
+ # "Highgprs" is kernel feature first implemented in Linux 2.6.32, see
+ # /proc/cpuinfo. The idea is to preserve most significant bits of
+@@ -437,12 +437,12 @@ my %table=(
+ #### SPARC Linux setups
+ # Ray Miller <ray.miller@computing-services.oxford.ac.uk> has patiently
+ # assisted with debugging of following two configs.
+-"linux-sparcv8","gcc:-mcpu=v8 -DB_ENDIAN -O3 -fomit-frame-pointer -Wall -DBN_DIV2W::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR:${sparcv8_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-sparcv8","gcc:-mcpu=v8 -DB_ENDIAN -Wall \$(RPM_OPT_FLAGS) -DBN_DIV2W::-D_REENTRANT::-Wl,-z,relro -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR:${sparcv8_asm}:dlfcn:linux-shared:-fPIC:\$(RPM_OPT_FLAGS):.so.\$(SHLIB_SONAMEVER)",
+ # it's a real mess with -mcpu=ultrasparc option under Linux, but
+ # -Wa,-Av8plus should do the trick no matter what.
+-"linux-sparcv9","gcc:-m32 -mcpu=ultrasparc -DB_ENDIAN -O3 -fomit-frame-pointer -Wall -Wa,-Av8plus -DBN_DIV2W::-D_REENTRANT:ULTRASPARC:-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR:${sparcv9_asm}:dlfcn:linux-shared:-fPIC:-m32:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)",
++"linux-sparcv9","gcc:-m32 -mcpu=ultrasparc -DB_ENDIAN -Wall \$(RPM_OPT_FLAGS) -Wa,-Av8plus -DBN_DIV2W::-D_REENTRANT:ULTRASPARC:-Wl,-z,relro -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR:${sparcv9_asm}:dlfcn:linux-shared:-fPIC:-m32 \$(RPM_OPT_FLAGS):.so.\$(SHLIB_SONAMEVER)",
+ # GCC 3.1 is a requirement
+-"linux64-sparcv9","gcc:-m64 -mcpu=ultrasparc -DB_ENDIAN -O3 -fomit-frame-pointer -Wall::-D_REENTRANT:ULTRASPARC:-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL BF_PTR:${sparcv9_asm}:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64",
++"linux64-sparcv9","gcc:-m64 -mcpu=ultrasparc -DB_ENDIAN -Wall \$(RPM_OPT_FLAGS)::-D_REENTRANT:ULTRASPARC:-Wl,-z,relro -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL BF_PTR:${sparcv9_asm}:dlfcn:linux-shared:-fPIC:-m64 \$(RPM_OPT_FLAGS):.so.\$(SHLIB_SONAMEVER):::64",
+ #### Alpha Linux with GNU C and Compaq C setups
+ # Special notes:
+ # - linux-alpha+bwx-gcc is ment to be used from ./config only. If you
+@@ -1767,7 +1767,7 @@ while (<IN>)
+ elsif ($shared_extension ne "" && $shared_extension =~ /^\.s([ol])\.[^\.]*\.[^\.]*$/)
+ {
+ my $sotmp = $1;
+- s/^SHARED_LIBS_LINK_EXTS=.*/SHARED_LIBS_LINK_EXTS=.s$sotmp.\$(SHLIB_MAJOR) .s$sotmp/;
++ s/^SHARED_LIBS_LINK_EXTS=.*/SHARED_LIBS_LINK_EXTS=.s$sotmp.\$(SHLIB_SONAMEVER) .s$sotmp/;
+ }
+ elsif ($shared_extension ne "" && $shared_extension =~ /^\.[^\.]*\.[^\.]*\.dylib$/)
+ {
+diff -up openssl-1.0.2e/Makefile.org.rpmbuild openssl-1.0.2e/Makefile.org
+--- openssl-1.0.2e/Makefile.org.rpmbuild 2015-12-03 15:04:23.000000000 +0100
++++ openssl-1.0.2e/Makefile.org 2015-12-04 13:18:44.913538616 +0100
+@@ -10,6 +10,7 @@ SHLIB_VERSION_HISTORY=
+ SHLIB_MAJOR=
+ SHLIB_MINOR=
+ SHLIB_EXT=
++SHLIB_SONAMEVER=10
+ PLATFORM=dist
+ OPTIONS=
+ CONFIGURE_ARGS=
+@@ -341,10 +342,9 @@ clean-shared:
+ link-shared:
+ @ set -e; for i in $(SHLIBDIRS); do \
+ $(MAKE) -f $(HERE)/Makefile.shared -e $(BUILDENV) \
+- LIBNAME=$$i LIBVERSION=$(SHLIB_MAJOR).$(SHLIB_MINOR) \
++ LIBNAME=$$i LIBVERSION=$(SHLIB_SONAMEVER) \
+ LIBCOMPATVERSIONS=";$(SHLIB_VERSION_HISTORY)" \
+ symlink.$(SHLIB_TARGET); \
+- libs="$$libs -l$$i"; \
+ done
+
+ build-shared: do_$(SHLIB_TARGET) link-shared
+@@ -355,7 +355,7 @@ do_$(SHLIB_TARGET):
+ libs="$(LIBKRB5) $$libs"; \
+ fi; \
+ $(CLEARENV) && $(MAKE) -f Makefile.shared -e $(BUILDENV) \
+- LIBNAME=$$i LIBVERSION=$(SHLIB_MAJOR).$(SHLIB_MINOR) \
++ LIBNAME=$$i LIBVERSION=$(SHLIB_SONAMEVER) \
+ LIBCOMPATVERSIONS=";$(SHLIB_VERSION_HISTORY)" \
+ LIBDEPS="$$libs $(EX_LIBS)" \
+ link_a.$(SHLIB_TARGET); \
--- /dev/null
+diff -Naur openssl-1.0.2a.org/crypto/x86cpuid.pl openssl-1.0.2a/crypto/x86cpuid.pl
+--- openssl-1.0.2a.org/crypto/x86cpuid.pl 2015-03-19 14:30:36.000000000 +0100
++++ openssl-1.0.2a/crypto/x86cpuid.pl 2015-04-28 13:47:57.853521020 +0200
+@@ -71,6 +71,7 @@
+ &mov ("eax",1);
+ &xor ("ecx","ecx");
+ &cpuid ();
++ &and ("ecx",0xfffffdff); # clear SSSE3 because it is incredible slow on AMD's
+ &bt ("edx",28);
+ &jnc (&label("generic"));
+ &shr ("ebx",16);
--- /dev/null
+diff -up openssl-1.0.2g/ssl/ssl_lib.c.v2v3 openssl-1.0.2g/ssl/ssl_lib.c
+--- openssl-1.0.2g/ssl/ssl_lib.c.v2v3 2016-03-01 16:38:26.879142021 +0100
++++ openssl-1.0.2g/ssl/ssl_lib.c 2016-03-01 16:41:32.977353769 +0100
+@@ -2055,11 +2055,11 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *m
+ ret->options |= SSL_OP_LEGACY_SERVER_CONNECT;
+
+ /*
+- * Disable SSLv2 by default, callers that want to enable SSLv2 will have to
+- * explicitly clear this option via either of SSL_CTX_clear_options() or
++ * Disable SSLv2 and SSLv3 by default, callers that want to enable these will have to
++ * explicitly clear these options via either of SSL_CTX_clear_options() or
+ * SSL_clear_options().
+ */
+- ret->options |= SSL_OP_NO_SSLv2;
++ ret->options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
+
+ return (ret);
+ err:
--- /dev/null
+From 8e508f23bf5ed727649c99bbd540f7b1c2c2bd35 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Stevan=20Baji=C4=87?= <stevan@bajic.ch>
+Date: Mon, 9 Jul 2012 09:43:11 +0200
+Subject: [PATCH] RLIMIT_* variables are no longer defined unless you
+ explicitly include sys/resource.h.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Diego Elio Pettenò <flameeyes@flameeyes.eu>
+
+modules/pam_unix/pam_unix_acct.c: Include sys/resource.h.
+---
+ modules/pam_unix/pam_unix_acct.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/modules/pam_unix/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c
+index 8e90cc9..4a362f8 100644
+--- a/modules/pam_unix/pam_unix_acct.c
++++ b/modules/pam_unix/pam_unix_acct.c
+@@ -41,6 +41,7 @@
+ #include <string.h>
+ #include <unistd.h>
+ #include <sys/types.h>
++#include <sys/resource.h>
+ #include <syslog.h>
+ #include <pwd.h>
+ #include <shadow.h>
--- /dev/null
+Submitted By: Ken Moffat <ken at linuxfromscratch dot org>
+Date: 2016-03-16
+Initial Package Version: 8.38
+Upstream Status: Applied
+Origin: Upstream, backported to 8.38 by Petr PÃsaÅ™ at redhat
+Description: Various fixes, including for CVE-2016-1263 and many other
+bugs which have been fixed upstream. Many of these bugs were found by
+fuzzing, upstream is trying to persuade its users to move to pcre2 and
+giving low priority to further pcre1 maintenance releases.
+
+From 3c80e02cd464ea049e117b423fd48fab294c51a9 Mon Sep 17 00:00:00 2001
+From: ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>
+Date: Thu, 26 Nov 2015 20:29:13 +0000
+Subject: [PATCH] Fix auto-callout (?# comment bug.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1611 2f5784b3-3f2a-0410-8824-cb99058d5e15
+
+Petr Pisar: Ported to 8.38.
+
+diff --git a/pcre_compile.c b/pcre_compile.c
+index 4d3b313..3360a8b 100644
+--- a/pcre_compile.c
++++ b/pcre_compile.c
+@@ -4699,6 +4699,23 @@ for (;; ptr++)
+ }
+ }
+
++ /* Skip over (?# comments. We need to do this here because we want to know if
++ the next thing is a quantifier, and these comments may come between an item
++ and its quantifier. */
++
++ if (c == CHAR_LEFT_PARENTHESIS && ptr[1] == CHAR_QUESTION_MARK &&
++ ptr[2] == CHAR_NUMBER_SIGN)
++ {
++ ptr += 3;
++ while (*ptr != CHAR_NULL && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
++ if (*ptr == CHAR_NULL)
++ {
++ *errorcodeptr = ERR18;
++ goto FAILED;
++ }
++ continue;
++ }
++
+ /* See if the next thing is a quantifier. */
+
+ is_quantifier =
+@@ -6529,21 +6546,6 @@ for (;; ptr++)
+ case CHAR_LEFT_PARENTHESIS:
+ ptr++;
+
+- /* First deal with comments. Putting this code right at the start ensures
+- that comments have no bad side effects. */
+-
+- if (ptr[0] == CHAR_QUESTION_MARK && ptr[1] == CHAR_NUMBER_SIGN)
+- {
+- ptr += 2;
+- while (*ptr != CHAR_NULL && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
+- if (*ptr == CHAR_NULL)
+- {
+- *errorcodeptr = ERR18;
+- goto FAILED;
+- }
+- continue;
+- }
+-
+ /* Now deal with various "verbs" that can be introduced by '*'. */
+
+ if (ptr[0] == CHAR_ASTERISK && (ptr[1] == ':'
+diff --git a/testdata/testinput2 b/testdata/testinput2
+index e2e520f..92e3359 100644
+--- a/testdata/testinput2
++++ b/testdata/testinput2
+@@ -4217,4 +4217,12 @@ backtracking verbs. --/
+
+ /a[[:punct:]b]/BZ
+
++/L(?#(|++<!(2)?/BZ
++
++/L(?#(|++<!(2)?/BOZ
++
++/L(?#(|++<!(2)?/BCZ
++
++/L(?#(|++<!(2)?/BCOZ
++
+ /-- End of testinput2 --/
+diff --git a/testdata/testinput7 b/testdata/testinput7
+index e411a4b..00b9738 100644
+--- a/testdata/testinput7
++++ b/testdata/testinput7
+@@ -853,4 +853,8 @@ of case for anything other than the ASCII letters. --/
+
+ /a[b[:punct:]]/8WBZ
+
++/L(?#(|++<!(2)?/B8COZ
++
++/L(?#(|++<!(2)?/B8WCZ
++
+ /-- End of testinput7 --/
+diff --git a/testdata/testoutput2 b/testdata/testoutput2
+index 85c565d..2cf7a90 100644
+--- a/testdata/testoutput2
++++ b/testdata/testoutput2
+@@ -14574,4 +14574,40 @@ No match
+ End
+ ------------------------------------------------------------------
+
++/L(?#(|++<!(2)?/BZ
++------------------------------------------------------------------
++ Bra
++ L?+
++ Ket
++ End
++------------------------------------------------------------------
++
++/L(?#(|++<!(2)?/BOZ
++------------------------------------------------------------------
++ Bra
++ L?
++ Ket
++ End
++------------------------------------------------------------------
++
++/L(?#(|++<!(2)?/BCZ
++------------------------------------------------------------------
++ Bra
++ Callout 255 0 14
++ L?+
++ Callout 255 14 0
++ Ket
++ End
++------------------------------------------------------------------
++
++/L(?#(|++<!(2)?/BCOZ
++------------------------------------------------------------------
++ Bra
++ Callout 255 0 14
++ L?
++ Callout 255 14 0
++ Ket
++ End
++------------------------------------------------------------------
++
+ /-- End of testinput2 --/
+diff --git a/testdata/testoutput7 b/testdata/testoutput7
+index cc9ebdd..fdfff64 100644
+--- a/testdata/testoutput7
++++ b/testdata/testoutput7
+@@ -2348,4 +2348,24 @@ No match
+ End
+ ------------------------------------------------------------------
+
++/L(?#(|++<!(2)?/B8COZ
++------------------------------------------------------------------
++ Bra
++ Callout 255 0 14
++ L?
++ Callout 255 14 0
++ Ket
++ End
++------------------------------------------------------------------
++
++/L(?#(|++<!(2)?/B8WCZ
++------------------------------------------------------------------
++ Bra
++ Callout 255 0 14
++ L?+
++ Callout 255 14 0
++ Ket
++ End
++------------------------------------------------------------------
++
+ /-- End of testinput7 --/
+--
+2.4.3
+
+From ef6b10fcde41a2687f38d4a9ff2886b037948a1b Mon Sep 17 00:00:00 2001
+From: ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>
+Date: Fri, 27 Nov 2015 17:13:13 +0000
+Subject: [PATCH 1/5] Fix negated POSIX class within negated overall class UCP
+ bug.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1612 2f5784b3-3f2a-0410-8824-cb99058d5e15
+
+Petr PÃsaÅ™: Ported to 8.38.
+diff --git a/pcre_compile.c b/pcre_compile.c
+index 3360a8b..3670f1e 100644
+--- a/pcre_compile.c
++++ b/pcre_compile.c
+@@ -5063,20 +5063,22 @@ for (;; ptr++)
+ ptr = tempptr + 1;
+ continue;
+
+- /* For the other POSIX classes (ascii, xdigit) we are going to fall
+- through to the non-UCP case and build a bit map for characters with
+- code points less than 256. If we are in a negated POSIX class
+- within a non-negated overall class, characters with code points
+- greater than 255 must all match. In the special case where we have
+- not yet generated any xclass data, and this is the final item in
+- the overall class, we need do nothing: later on, the opcode
++ /* For the other POSIX classes (ascii, cntrl, xdigit) we are going
++ to fall through to the non-UCP case and build a bit map for
++ characters with code points less than 256. If we are in a negated
++ POSIX class, characters with code points greater than 255 must
++ either all match or all not match. In the special case where we
++ have not yet generated any xclass data, and this is the final item
++ in the overall class, we need do nothing: later on, the opcode
+ OP_NCLASS will be used to indicate that characters greater than 255
+ are acceptable. If we have already seen an xclass item or one may
+ follow (we have to assume that it might if this is not the end of
+- the class), explicitly match all wide codepoints. */
++ the class), explicitly list all wide codepoints, which will then
++ either not match or match, depending on whether the class is or is
++ not negated. */
+
+ default:
+- if (!negate_class && local_negate &&
++ if (local_negate &&
+ (xclass || tempptr[2] != CHAR_RIGHT_SQUARE_BRACKET))
+ {
+ *class_uchardata++ = XCL_RANGE;
+diff --git a/testdata/testinput6 b/testdata/testinput6
+index aeb62a0..a178d3d 100644
+--- a/testdata/testinput6
++++ b/testdata/testinput6
+@@ -1553,4 +1553,13 @@
+ \x{200}
+ \x{37e}
+
++/[^[:^ascii:]\d]/8W
++ a
++ ~
++ 0
++ \a
++ \x{7f}
++ \x{389}
++ \x{20ac}
++
+ /-- End of testinput6 --/
+diff --git a/testdata/testoutput6 b/testdata/testoutput6
+index beb85aa..b64dc0d 100644
+--- a/testdata/testoutput6
++++ b/testdata/testoutput6
+@@ -2557,4 +2557,20 @@ No match
+ \x{37e}
+ 0: \x{37e}
+
++/[^[:^ascii:]\d]/8W
++ a
++ 0: a
++ ~
++ 0: ~
++ 0
++No match
++ \a
++ 0: \x{07}
++ \x{7f}
++ 0: \x{7f}
++ \x{389}
++No match
++ \x{20ac}
++No match
++
+ /-- End of testinput6 --/
+--
+2.4.3
+
+From bfc1dfa660c24dc7a75108d934290e50d7db2719 Mon Sep 17 00:00:00 2001
+From: ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>
+Date: Fri, 27 Nov 2015 17:41:04 +0000
+Subject: [PATCH 2/5] Fix bug for isolated \E between an item and its qualifier
+ when auto callout is set.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1613 2f5784b3-3f2a-0410-8824-cb99058d5e15
+
+Petr PÃsaÅ™: Ported to 8.38.
+
+diff --git a/pcre_compile.c b/pcre_compile.c
+index 3670f1e..5786cd3 100644
+--- a/pcre_compile.c
++++ b/pcre_compile.c
+@@ -4645,9 +4645,10 @@ for (;; ptr++)
+ goto FAILED;
+ }
+
+- /* If in \Q...\E, check for the end; if not, we have a literal */
++ /* If in \Q...\E, check for the end; if not, we have a literal. Otherwise an
++ isolated \E is ignored. */
+
+- if (inescq && c != CHAR_NULL)
++ if (c != CHAR_NULL)
+ {
+ if (c == CHAR_BACKSLASH && ptr[1] == CHAR_E)
+ {
+@@ -4655,7 +4656,7 @@ for (;; ptr++)
+ ptr++;
+ continue;
+ }
+- else
++ else if (inescq)
+ {
+ if (previous_callout != NULL)
+ {
+@@ -4670,7 +4671,6 @@ for (;; ptr++)
+ }
+ goto NORMAL_CHAR;
+ }
+- /* Control does not reach here. */
+ }
+
+ /* In extended mode, skip white space and comments. We need a loop in order
+diff --git a/testdata/testinput2 b/testdata/testinput2
+index 92e3359..e8ca4fe 100644
+--- a/testdata/testinput2
++++ b/testdata/testinput2
+@@ -4225,4 +4225,6 @@ backtracking verbs. --/
+
+ /L(?#(|++<!(2)?/BCOZ
+
++/(A*)\E+/CBZ
++
+ /-- End of testinput2 --/
+diff --git a/testdata/testoutput2 b/testdata/testoutput2
+index 2cf7a90..09756b8 100644
+--- a/testdata/testoutput2
++++ b/testdata/testoutput2
+@@ -14610,4 +14610,18 @@ No match
+ End
+ ------------------------------------------------------------------
+
++/(A*)\E+/CBZ
++------------------------------------------------------------------
++ Bra
++ Callout 255 0 7
++ SCBra 1
++ Callout 255 1 2
++ A*
++ Callout 255 3 0
++ KetRmax
++ Callout 255 7 0
++ Ket
++ End
++------------------------------------------------------------------
++
+ /-- End of testinput2 --/
+--
+2.4.3
+
+From 108377b836fc29a84f5286287629d96549b1c777 Mon Sep 17 00:00:00 2001
+From: ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>
+Date: Sun, 29 Nov 2015 17:38:25 +0000
+Subject: [PATCH 3/5] Give error for regexec with pmatch=NULL and REG_STARTEND
+ set.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1614 2f5784b3-3f2a-0410-8824-cb99058d5e15
+
+Petr PÃsaÅ™: Ported to 8.38.
+
+diff --git a/pcreposix.c b/pcreposix.c
+index f024423..dcc13ef 100644
+--- a/pcreposix.c
++++ b/pcreposix.c
+@@ -364,6 +364,7 @@ start location rather than being passed as a PCRE "starting offset". */
+
+ if ((eflags & REG_STARTEND) != 0)
+ {
++ if (pmatch == NULL) return REG_INVARG;
+ so = pmatch[0].rm_so;
+ eo = pmatch[0].rm_eo;
+ }
+--
+2.4.3
+
+From e347b40d5bb12f7ef1e632aa649571a107be7d8a Mon Sep 17 00:00:00 2001
+From: ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>
+Date: Sun, 29 Nov 2015 17:46:23 +0000
+Subject: [PATCH 4/5] Allow for up to 32-bit numbers in the ordin() function in
+ pcregrep.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1615 2f5784b3-3f2a-0410-8824-cb99058d5e15
+
+Petr PÃsaÅ™: Ported to 8.38.
+
+diff --git a/pcregrep.c b/pcregrep.c
+index 64986b0..cd53c64 100644
+--- a/pcregrep.c
++++ b/pcregrep.c
+@@ -2437,7 +2437,7 @@ return options;
+ static char *
+ ordin(int n)
+ {
+-static char buffer[8];
++static char buffer[14];
+ char *p = buffer;
+ sprintf(p, "%d", n);
+ while (*p != 0) p++;
+--
+2.4.3
+
+From e78ad4264b16988b826bd2939a1781c1165a92d9 Mon Sep 17 00:00:00 2001
+From: ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>
+Date: Mon, 30 Nov 2015 17:44:45 +0000
+Subject: [PATCH 5/5] Fix \Q\E before qualifier bug when auto callouts are
+ enabled.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1616 2f5784b3-3f2a-0410-8824-cb99058d5e15
+
+Petr PÃsaÅ™: Ported to 8.38.
+
+diff --git a/pcre_compile.c b/pcre_compile.c
+index 5786cd3..beed46b 100644
+--- a/pcre_compile.c
++++ b/pcre_compile.c
+@@ -4671,17 +4671,27 @@ for (;; ptr++)
+ }
+ goto NORMAL_CHAR;
+ }
++
++ /* Check for the start of a \Q...\E sequence. We must do this here rather
++ than later in case it is immediately followed by \E, which turns it into a
++ "do nothing" sequence. */
++
++ if (c == CHAR_BACKSLASH && ptr[1] == CHAR_Q)
++ {
++ inescq = TRUE;
++ ptr++;
++ continue;
++ }
+ }
+
+- /* In extended mode, skip white space and comments. We need a loop in order
+- to check for more white space and more comments after a comment. */
++ /* In extended mode, skip white space and comments. */
+
+ if ((options & PCRE_EXTENDED) != 0)
+ {
+- for (;;)
++ const pcre_uchar *wscptr = ptr;
++ while (MAX_255(c) && (cd->ctypes[c] & ctype_space) != 0) c = *(++ptr);
++ if (c == CHAR_NUMBER_SIGN)
+ {
+- while (MAX_255(c) && (cd->ctypes[c] & ctype_space) != 0) c = *(++ptr);
+- if (c != CHAR_NUMBER_SIGN) break;
+ ptr++;
+ while (*ptr != CHAR_NULL)
+ {
+@@ -4695,7 +4705,15 @@ for (;; ptr++)
+ if (utf) FORWARDCHAR(ptr);
+ #endif
+ }
+- c = *ptr; /* Either NULL or the char after a newline */
++ }
++
++ /* If we skipped any characters, restart the loop. Otherwise, we didn't see
++ a comment. */
++
++ if (ptr > wscptr)
++ {
++ ptr--;
++ continue;
+ }
+ }
+
+@@ -7900,16 +7918,6 @@ for (;; ptr++)
+ c = ec;
+ else
+ {
+- if (escape == ESC_Q) /* Handle start of quoted string */
+- {
+- if (ptr[1] == CHAR_BACKSLASH && ptr[2] == CHAR_E)
+- ptr += 2; /* avoid empty string */
+- else inescq = TRUE;
+- continue;
+- }
+-
+- if (escape == ESC_E) continue; /* Perl ignores an orphan \E */
+-
+ /* For metasequences that actually match a character, we disable the
+ setting of a first character if it hasn't already been set. */
+
+diff --git a/testdata/testinput2 b/testdata/testinput2
+index e8ca4fe..3a1134f 100644
+--- a/testdata/testinput2
++++ b/testdata/testinput2
+@@ -4227,4 +4227,6 @@ backtracking verbs. --/
+
+ /(A*)\E+/CBZ
+
++/()\Q\E*]/BCZ
++
+ /-- End of testinput2 --/
+diff --git a/testdata/testoutput2 b/testdata/testoutput2
+index 09756b8..ac33cc4 100644
+--- a/testdata/testoutput2
++++ b/testdata/testoutput2
+@@ -14624,4 +14624,19 @@ No match
+ End
+ ------------------------------------------------------------------
+
++/()\Q\E*]/BCZ
++------------------------------------------------------------------
++ Bra
++ Callout 255 0 7
++ Brazero
++ SCBra 1
++ Callout 255 1 0
++ KetRmax
++ Callout 255 7 1
++ ]
++ Callout 255 8 0
++ Ket
++ End
++------------------------------------------------------------------
++
+ /-- End of testinput2 --/
+--
+2.4.3
+
+From 46ed1a703b067e5b679eacf6500a54dae35f8130 Mon Sep 17 00:00:00 2001
+From: ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>
+Date: Thu, 3 Dec 2015 17:05:40 +0000
+Subject: [PATCH] Fix /x bug when pattern starts with white space and (?-x)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1617 2f5784b3-3f2a-0410-8824-cb99058d5e15
+
+Petr PÃsaÅ™: Ported to 8.38.
+
+diff --git a/pcre_compile.c b/pcre_compile.c
+index beed46b..57719b9 100644
+--- a/pcre_compile.c
++++ b/pcre_compile.c
+@@ -7607,39 +7607,15 @@ for (;; ptr++)
+ newoptions = (options | set) & (~unset);
+
+ /* If the options ended with ')' this is not the start of a nested
+- group with option changes, so the options change at this level. If this
+- item is right at the start of the pattern, the options can be
+- abstracted and made external in the pre-compile phase, and ignored in
+- the compile phase. This can be helpful when matching -- for instance in
+- caseless checking of required bytes.
+-
+- If the code pointer is not (cd->start_code + 1 + LINK_SIZE), we are
+- definitely *not* at the start of the pattern because something has been
+- compiled. In the pre-compile phase, however, the code pointer can have
+- that value after the start, because it gets reset as code is discarded
+- during the pre-compile. However, this can happen only at top level - if
+- we are within parentheses, the starting BRA will still be present. At
+- any parenthesis level, the length value can be used to test if anything
+- has been compiled at that level. Thus, a test for both these conditions
+- is necessary to ensure we correctly detect the start of the pattern in
+- both phases.
+-
++ group with option changes, so the options change at this level.
+ If we are not at the pattern start, reset the greedy defaults and the
+ case value for firstchar and reqchar. */
+
+ if (*ptr == CHAR_RIGHT_PARENTHESIS)
+ {
+- if (code == cd->start_code + 1 + LINK_SIZE &&
+- (lengthptr == NULL || *lengthptr == 2 + 2*LINK_SIZE))
+- {
+- cd->external_options = newoptions;
+- }
+- else
+- {
+- greedy_default = ((newoptions & PCRE_UNGREEDY) != 0);
+- greedy_non_default = greedy_default ^ 1;
+- req_caseopt = ((newoptions & PCRE_CASELESS) != 0)? REQ_CASELESS:0;
+- }
++ greedy_default = ((newoptions & PCRE_UNGREEDY) != 0);
++ greedy_non_default = greedy_default ^ 1;
++ req_caseopt = ((newoptions & PCRE_CASELESS) != 0)? REQ_CASELESS:0;
+
+ /* Change options at this level, and pass them back for use
+ in subsequent branches. */
+diff --git a/testdata/testoutput2 b/testdata/testoutput2
+index ac33cc4..6c42897 100644
+--- a/testdata/testoutput2
++++ b/testdata/testoutput2
+@@ -419,7 +419,7 @@ Need char = '>'
+
+ /(?U)<.*>/I
+ Capturing subpattern count = 0
+-Options: ungreedy
++No options
+ First char = '<'
+ Need char = '>'
+ abc<def>ghi<klm>nop
+@@ -443,7 +443,7 @@ Need char = '='
+
+ /(?U)={3,}?/I
+ Capturing subpattern count = 0
+-Options: ungreedy
++No options
+ First char = '='
+ Need char = '='
+ abc========def
+@@ -477,7 +477,7 @@ Failed: lookbehind assertion is not fixed length at offset 12
+
+ /(?i)abc/I
+ Capturing subpattern count = 0
+-Options: caseless
++No options
+ First char = 'a' (caseless)
+ Need char = 'c' (caseless)
+
+@@ -489,7 +489,7 @@ No need char
+
+ /(?i)^1234/I
+ Capturing subpattern count = 0
+-Options: anchored caseless
++Options: anchored
+ No first char
+ No need char
+
+@@ -502,7 +502,7 @@ No need char
+ /(?s).*/I
+ Capturing subpattern count = 0
+ May match empty string
+-Options: anchored dotall
++Options: anchored
+ No first char
+ No need char
+
+@@ -516,7 +516,7 @@ Starting chars: a b c d
+
+ /(?i)[abcd]/IS
+ Capturing subpattern count = 0
+-Options: caseless
++No options
+ No first char
+ No need char
+ Subject length lower bound = 1
+@@ -524,7 +524,7 @@ Starting chars: A B C D a b c d
+
+ /(?m)[xy]|(b|c)/IS
+ Capturing subpattern count = 1
+-Options: multiline
++No options
+ No first char
+ No need char
+ Subject length lower bound = 1
+@@ -538,7 +538,7 @@ No need char
+
+ /(?i)(^a|^b)/Im
+ Capturing subpattern count = 1
+-Options: caseless multiline
++Options: multiline
+ First char at start or follows newline
+ No need char
+
+@@ -1179,7 +1179,7 @@ No need char
+ End
+ ------------------------------------------------------------------
+ Capturing subpattern count = 1
+-Options: anchored dotall
++Options: anchored
+ No first char
+ No need char
+
+@@ -2735,7 +2735,7 @@ No match
+ End
+ ------------------------------------------------------------------
+ Capturing subpattern count = 0
+-Options: caseless extended
++Options: extended
+ First char = 'a' (caseless)
+ Need char = 'c' (caseless)
+
+@@ -2748,7 +2748,7 @@ Need char = 'c' (caseless)
+ End
+ ------------------------------------------------------------------
+ Capturing subpattern count = 0
+-Options: caseless extended
++Options: extended
+ First char = 'a' (caseless)
+ Need char = 'c' (caseless)
+
+@@ -3095,7 +3095,7 @@ Need char = 'b'
+ End
+ ------------------------------------------------------------------
+ Capturing subpattern count = 0
+-Options: ungreedy
++No options
+ First char = 'x'
+ Need char = 'b'
+ xaaaab
+@@ -3497,7 +3497,7 @@ Need char = 'c'
+
+ /(?i)[ab]/IS
+ Capturing subpattern count = 0
+-Options: caseless
++No options
+ No first char
+ No need char
+ Subject length lower bound = 1
+@@ -6299,7 +6299,7 @@ Capturing subpattern count = 3
+ Named capturing subpatterns:
+ A 2
+ A 3
+-Options: anchored dupnames
++Options: anchored
+ Duplicate name status changes
+ No first char
+ No need char
+--
+2.4.3
+
+From db1fb68feddc9afe6f8822d099fa9ff25e3ea8e7 Mon Sep 17 00:00:00 2001
+From: ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>
+Date: Sat, 5 Dec 2015 16:30:14 +0000
+Subject: [PATCH] Fix copy named substring bug.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1618 2f5784b3-3f2a-0410-8824-cb99058d5e15
+
+Petr PÃsaÅ™: Ported to 8.38.
+diff --git a/pcre_get.c b/pcre_get.c
+index 8094b34..41eda9c 100644
+--- a/pcre_get.c
++++ b/pcre_get.c
+@@ -250,6 +250,7 @@ Arguments:
+ code the compiled regex
+ stringname the name of the capturing substring
+ ovector the vector of matched substrings
++ stringcount number of captured substrings
+
+ Returns: the number of the first that is set,
+ or the number of the last one if none are set,
+@@ -258,13 +259,16 @@ Returns: the number of the first that is set,
+
+ #if defined COMPILE_PCRE8
+ static int
+-get_first_set(const pcre *code, const char *stringname, int *ovector)
++get_first_set(const pcre *code, const char *stringname, int *ovector,
++ int stringcount)
+ #elif defined COMPILE_PCRE16
+ static int
+-get_first_set(const pcre16 *code, PCRE_SPTR16 stringname, int *ovector)
++get_first_set(const pcre16 *code, PCRE_SPTR16 stringname, int *ovector,
++ int stringcount)
+ #elif defined COMPILE_PCRE32
+ static int
+-get_first_set(const pcre32 *code, PCRE_SPTR32 stringname, int *ovector)
++get_first_set(const pcre32 *code, PCRE_SPTR32 stringname, int *ovector,
++ int stringcount)
+ #endif
+ {
+ const REAL_PCRE *re = (const REAL_PCRE *)code;
+@@ -295,7 +299,7 @@ if (entrysize <= 0) return entrysize;
+ for (entry = (pcre_uchar *)first; entry <= (pcre_uchar *)last; entry += entrysize)
+ {
+ int n = GET2(entry, 0);
+- if (ovector[n*2] >= 0) return n;
++ if (n < stringcount && ovector[n*2] >= 0) return n;
+ }
+ return GET2(entry, 0);
+ }
+@@ -402,7 +406,7 @@ pcre32_copy_named_substring(const pcre32 *code, PCRE_SPTR32 subject,
+ PCRE_UCHAR32 *buffer, int size)
+ #endif
+ {
+-int n = get_first_set(code, stringname, ovector);
++int n = get_first_set(code, stringname, ovector, stringcount);
+ if (n <= 0) return n;
+ #if defined COMPILE_PCRE8
+ return pcre_copy_substring(subject, ovector, stringcount, n, buffer, size);
+@@ -619,7 +623,7 @@ pcre32_get_named_substring(const pcre32 *code, PCRE_SPTR32 subject,
+ PCRE_SPTR32 *stringptr)
+ #endif
+ {
+-int n = get_first_set(code, stringname, ovector);
++int n = get_first_set(code, stringname, ovector, stringcount);
+ if (n <= 0) return n;
+ #if defined COMPILE_PCRE8
+ return pcre_get_substring(subject, ovector, stringcount, n, stringptr);
+diff --git a/testdata/testinput2 b/testdata/testinput2
+index 3a1134f..00ffe32 100644
+--- a/testdata/testinput2
++++ b/testdata/testinput2
+@@ -4229,4 +4229,7 @@ backtracking verbs. --/
+
+ /()\Q\E*]/BCZ
+
++/(?<A>)(?J:(?<B>)(?<B>))(?<C>)/
++ \O\CC
++
+ /-- End of testinput2 --/
+diff --git a/testdata/testoutput2 b/testdata/testoutput2
+index 6c42897..ffb4466 100644
+--- a/testdata/testoutput2
++++ b/testdata/testoutput2
+@@ -14639,4 +14639,9 @@ No match
+ End
+ ------------------------------------------------------------------
+
++/(?<A>)(?J:(?<B>)(?<B>))(?<C>)/
++ \O\CC
++Matched, but too many substrings
++copy substring C failed -7
++
+ /-- End of testinput2 --/
+--
+2.4.3
+
+From 40363ebc19baeab160abaaa55dc84322a89ac35a Mon Sep 17 00:00:00 2001
+From: ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>
+Date: Sat, 5 Dec 2015 16:58:46 +0000
+Subject: [PATCH] Fix (by hacking) another length computation issue.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1619 2f5784b3-3f2a-0410-8824-cb99058d5e15
+
+Petr PÃsaÅ™: Ported to 8.38.
+
+diff --git a/pcre_compile.c b/pcre_compile.c
+index 57719b9..087bf2a 100644
+--- a/pcre_compile.c
++++ b/pcre_compile.c
+@@ -7280,7 +7280,7 @@ for (;; ptr++)
+ issue is fixed "properly" in PCRE2. As PCRE1 is now in maintenance
+ only mode, we finesse the bug by allowing more memory always. */
+
+- *lengthptr += 2 + 2*LINK_SIZE;
++ *lengthptr += 4 + 4*LINK_SIZE;
+
+ /* It is even worse than that. The current reference may be to an
+ existing named group with a different number (so apparently not
+diff --git a/testdata/testoutput11-16 b/testdata/testoutput11-16
+index 9a0a12d..280692e 100644
+--- a/testdata/testoutput11-16
++++ b/testdata/testoutput11-16
+@@ -231,7 +231,7 @@ Memory allocation (code space): 73
+ ------------------------------------------------------------------
+
+ /(?P<a>a)...(?P=a)bbb(?P>a)d/BM
+-Memory allocation (code space): 77
++Memory allocation (code space): 93
+ ------------------------------------------------------------------
+ 0 24 Bra
+ 2 5 CBra 1
+diff --git a/testdata/testoutput11-32 b/testdata/testoutput11-32
+index 57e5da0..cdbda74 100644
+--- a/testdata/testoutput11-32
++++ b/testdata/testoutput11-32
+@@ -231,7 +231,7 @@ Memory allocation (code space): 155
+ ------------------------------------------------------------------
+
+ /(?P<a>a)...(?P=a)bbb(?P>a)d/BM
+-Memory allocation (code space): 157
++Memory allocation (code space): 189
+ ------------------------------------------------------------------
+ 0 24 Bra
+ 2 5 CBra 1
+diff --git a/testdata/testoutput11-8 b/testdata/testoutput11-8
+index 748548a..cb37896 100644
+--- a/testdata/testoutput11-8
++++ b/testdata/testoutput11-8
+@@ -231,7 +231,7 @@ Memory allocation (code space): 45
+ ------------------------------------------------------------------
+
+ /(?P<a>a)...(?P=a)bbb(?P>a)d/BM
+-Memory allocation (code space): 50
++Memory allocation (code space): 62
+ ------------------------------------------------------------------
+ 0 30 Bra
+ 3 7 CBra 1
+--
+2.4.3
+
+From 4f47274a2eb10131d88145ad7fd0eed4027a0c51 Mon Sep 17 00:00:00 2001
+From: ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>
+Date: Tue, 8 Dec 2015 11:06:40 +0000
+Subject: [PATCH] Fix get_substring_list() bug when \K is used in an assertion.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1620 2f5784b3-3f2a-0410-8824-cb99058d5e15
+
+Petr PÃsaÅ™: ported to 8.38.
+
+diff --git a/pcre_get.c b/pcre_get.c
+index 41eda9c..cdd2abc 100644
+--- a/pcre_get.c
++++ b/pcre_get.c
+@@ -461,7 +461,10 @@ pcre_uchar **stringlist;
+ pcre_uchar *p;
+
+ for (i = 0; i < double_count; i += 2)
+- size += sizeof(pcre_uchar *) + IN_UCHARS(ovector[i+1] - ovector[i] + 1);
++ {
++ size += sizeof(pcre_uchar *) + IN_UCHARS(1);
++ if (ovector[i+1] > ovector[i]) size += IN_UCHARS(ovector[i+1] - ovector[i]);
++ }
+
+ stringlist = (pcre_uchar **)(PUBL(malloc))(size);
+ if (stringlist == NULL) return PCRE_ERROR_NOMEMORY;
+@@ -477,7 +480,7 @@ p = (pcre_uchar *)(stringlist + stringcount + 1);
+
+ for (i = 0; i < double_count; i += 2)
+ {
+- int len = ovector[i+1] - ovector[i];
++ int len = (ovector[i+1] > ovector[i])? (ovector[i+1] - ovector[i]) : 0;
+ memcpy(p, subject + ovector[i], IN_UCHARS(len));
+ *stringlist++ = p;
+ p += len;
+diff --git a/testdata/testinput2 b/testdata/testinput2
+index 00ffe32..967a241 100644
+--- a/testdata/testinput2
++++ b/testdata/testinput2
+@@ -4232,4 +4232,7 @@ backtracking verbs. --/
+ /(?<A>)(?J:(?<B>)(?<B>))(?<C>)/
+ \O\CC
+
++/(?=a\K)/
++ ring bpattingbobnd $ 1,oern cou \rb\L
++
+ /-- End of testinput2 --/
+diff --git a/testdata/testoutput2 b/testdata/testoutput2
+index ffb4466..5fb28d5 100644
+--- a/testdata/testoutput2
++++ b/testdata/testoutput2
+@@ -14644,4 +14644,10 @@ No match
+ Matched, but too many substrings
+ copy substring C failed -7
+
++/(?=a\K)/
++ ring bpattingbobnd $ 1,oern cou \rb\L
++Start of matched string is beyond its end - displaying from end to start.
++ 0: a
++ 0L
++
+ /-- End of testinput2 --/
+--
+2.5.0
+
+From 3da5528b47b88c32224cf9d14d8a4e80cd7a0815 Mon Sep 17 00:00:00 2001
+From: ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>
+Date: Sat, 6 Feb 2016 16:54:14 +0000
+Subject: [PATCH] Fix pcretest bad behaviour for callout in lookbehind.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1625 2f5784b3-3f2a-0410-8824-cb99058d5e15
+
+Petr PÃsaÅ™: Ported to 8.38.
+
+diff --git a/pcretest.c b/pcretest.c
+index 488e419..63869fd 100644
+--- a/pcretest.c
++++ b/pcretest.c
+@@ -2250,7 +2250,7 @@ data is not zero. */
+ static int callout(pcre_callout_block *cb)
+ {
+ FILE *f = (first_callout | callout_extra)? outfile : NULL;
+-int i, pre_start, post_start, subject_length;
++int i, current_position, pre_start, post_start, subject_length;
+
+ if (callout_extra)
+ {
+@@ -2280,14 +2280,19 @@ printed lengths of the substrings. */
+
+ if (f != NULL) fprintf(f, "--->");
+
++/* If a lookbehind is involved, the current position may be earlier than the
++match start. If so, use the match start instead. */
++
++current_position = (cb->current_position >= cb->start_match)?
++ cb->current_position : cb->start_match;
++
+ PCHARS(pre_start, cb->subject, 0, cb->start_match, f);
+ PCHARS(post_start, cb->subject, cb->start_match,
+- cb->current_position - cb->start_match, f);
++ current_position - cb->start_match, f);
+
+ PCHARS(subject_length, cb->subject, 0, cb->subject_length, NULL);
+
+-PCHARSV(cb->subject, cb->current_position,
+- cb->subject_length - cb->current_position, f);
++PCHARSV(cb->subject, current_position, cb->subject_length - current_position, f);
+
+ if (f != NULL) fprintf(f, "\n");
+
+@@ -5740,3 +5745,4 @@ return yield;
+ }
+
+ /* End of pcretest.c */
++
+diff --git a/testdata/testinput2 b/testdata/testinput2
+index 967a241..086e0f4 100644
+--- a/testdata/testinput2
++++ b/testdata/testinput2
+@@ -4235,4 +4235,8 @@ backtracking verbs. --/
+ /(?=a\K)/
+ ring bpattingbobnd $ 1,oern cou \rb\L
+
++/(?<=((?C)0))/
++ 9010
++ abcd
++
+ /-- End of testinput2 --/
+diff --git a/testdata/testoutput2 b/testdata/testoutput2
+index 5fb28d5..d414a72 100644
+--- a/testdata/testoutput2
++++ b/testdata/testoutput2
+@@ -14650,4 +14650,19 @@ Start of matched string is beyond its end - displaying from end to start.
+ 0: a
+ 0L
+
++/(?<=((?C)0))/
++ 9010
++--->9010
++ 0 ^ 0
++ 0 ^ 0
++ 0:
++ 1: 0
++ abcd
++--->abcd
++ 0 ^ 0
++ 0 ^ 0
++ 0 ^ 0
++ 0 ^ 0
++No match
++
+ /-- End of testinput2 --/
+--
+2.5.0
+
+From 943a5105b9fe2842851003f692c7077a6cdbeefe Mon Sep 17 00:00:00 2001
+From: ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>
+Date: Wed, 10 Feb 2016 19:13:17 +0000
+Subject: [PATCH] Fix workspace overflow for (*ACCEPT) with deeply nested
+ parentheses.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1631 2f5784b3-3f2a-0410-8824-cb99058d5e15
+
+Petr PÃsaÅ™: Ported to 8.38.
+
+diff --git a/pcre_compile.c b/pcre_compile.c
+index b9a239e..5019854 100644
+--- a/pcre_compile.c
++++ b/pcre_compile.c
+@@ -6,7 +6,7 @@
+ and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+- Copyright (c) 1997-2014 University of Cambridge
++ Copyright (c) 1997-2016 University of Cambridge
+
+ -----------------------------------------------------------------------------
+ Redistribution and use in source and binary forms, with or without
+@@ -560,6 +560,7 @@ static const char error_texts[] =
+ /* 85 */
+ "parentheses are too deeply nested (stack check)\0"
+ "digits missing in \\x{} or \\o{}\0"
++ "regular expression is too complicated\0"
+ ;
+
+ /* Table to identify digits and hex digits. This is used when compiling
+@@ -4591,7 +4592,8 @@ for (;; ptr++)
+ if (code > cd->start_workspace + cd->workspace_size -
+ WORK_SIZE_SAFETY_MARGIN) /* Check for overrun */
+ {
+- *errorcodeptr = ERR52;
++ *errorcodeptr = (code >= cd->start_workspace + cd->workspace_size)?
++ ERR52 : ERR87;
+ goto FAILED;
+ }
+
+@@ -6626,8 +6628,21 @@ for (;; ptr++)
+ cd->had_accept = TRUE;
+ for (oc = cd->open_caps; oc != NULL; oc = oc->next)
+ {
+- *code++ = OP_CLOSE;
+- PUT2INC(code, 0, oc->number);
++ if (lengthptr != NULL)
++ {
++#ifdef COMPILE_PCRE8
++ *lengthptr += 1 + IMM2_SIZE;
++#elif defined COMPILE_PCRE16
++ *lengthptr += 2 + IMM2_SIZE;
++#elif defined COMPILE_PCRE32
++ *lengthptr += 4 + IMM2_SIZE;
++#endif
++ }
++ else
++ {
++ *code++ = OP_CLOSE;
++ PUT2INC(code, 0, oc->number);
++ }
+ }
+ setverb = *code++ =
+ (cd->assert_depth > 0)? OP_ASSERT_ACCEPT : OP_ACCEPT;
+diff --git a/pcre_internal.h b/pcre_internal.h
+index f7a5ee7..dbfe80e 100644
+--- a/pcre_internal.h
++++ b/pcre_internal.h
+@@ -7,7 +7,7 @@
+ and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+- Copyright (c) 1997-2014 University of Cambridge
++ Copyright (c) 1997-2016 University of Cambridge
+
+ -----------------------------------------------------------------------------
+ Redistribution and use in source and binary forms, with or without
+@@ -2289,7 +2289,7 @@ enum { ERR0, ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9,
+ ERR50, ERR51, ERR52, ERR53, ERR54, ERR55, ERR56, ERR57, ERR58, ERR59,
+ ERR60, ERR61, ERR62, ERR63, ERR64, ERR65, ERR66, ERR67, ERR68, ERR69,
+ ERR70, ERR71, ERR72, ERR73, ERR74, ERR75, ERR76, ERR77, ERR78, ERR79,
+- ERR80, ERR81, ERR82, ERR83, ERR84, ERR85, ERR86, ERRCOUNT };
++ ERR80, ERR81, ERR82, ERR83, ERR84, ERR85, ERR86, ERR87, ERRCOUNT };
+
+ /* JIT compiling modes. The function list is indexed by them. */
+
+diff --git a/pcreposix.c b/pcreposix.c
+index dcc13ef..55b6ddc 100644
+--- a/pcreposix.c
++++ b/pcreposix.c
+@@ -6,7 +6,7 @@
+ and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+- Copyright (c) 1997-2014 University of Cambridge
++ Copyright (c) 1997-2016 University of Cambridge
+
+ -----------------------------------------------------------------------------
+ Redistribution and use in source and binary forms, with or without
+@@ -173,7 +173,8 @@ static const int eint[] = {
+ REG_BADPAT, /* group name must start with a non-digit */
+ /* 85 */
+ REG_BADPAT, /* parentheses too deeply nested (stack check) */
+- REG_BADPAT /* missing digits in \x{} or \o{} */
++ REG_BADPAT, /* missing digits in \x{} or \o{} */
++ REG_BADPAT /* pattern too complicated */
+ };
+
+ /* Table of texts corresponding to POSIX error codes */
+diff --git a/testdata/testinput11 b/testdata/testinput11
+index ac9d228..6f0989a 100644
+--- a/testdata/testinput11
++++ b/testdata/testinput11
+@@ -138,4 +138,6 @@ is required for these tests. --/
+
+ /.((?2)(?R)\1)()/B
+
++/([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/
++
+ /-- End of testinput11 --/
+diff --git a/testdata/testoutput11-16 b/testdata/testoutput11-16
+index 280692e..3c485da 100644
+--- a/testdata/testoutput11-16
++++ b/testdata/testoutput11-16
+@@ -765,4 +765,7 @@ Memory allocation (code space): 14
+ 25 End
+ ------------------------------------------------------------------
+
++/([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/
++Failed: regular expression is too complicated at offset 490
++
+ /-- End of testinput11 --/
+diff --git a/testdata/testoutput11-32 b/testdata/testoutput11-32
+index cdbda74..e19518d 100644
+--- a/testdata/testoutput11-32
++++ b/testdata/testoutput11-32
+@@ -765,4 +765,7 @@ Memory allocation (code space): 28
+ 25 End
+ ------------------------------------------------------------------
+
++/([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/
++Failed: missing ) at offset 509
++
+ /-- End of testinput11 --/
+diff --git a/testdata/testoutput11-8 b/testdata/testoutput11-8
+index cb37896..5a4fbb2 100644
+--- a/testdata/testoutput11-8
++++ b/testdata/testoutput11-8
+@@ -765,4 +765,7 @@ Memory allocation (code space): 10
+ 38 End
+ ------------------------------------------------------------------
+
++/([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/
++Failed: missing ) at offset 509
++
+ /-- End of testinput11 --/
+--
+2.5.0
+
+From b7537308b7c758f33c347cb0bec62754c43c271f Mon Sep 17 00:00:00 2001
+From: ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>
+Date: Sat, 27 Feb 2016 17:38:11 +0000
+Subject: [PATCH] Yet another duplicate name bugfix by overestimating the
+ memory needed (i.e. another hack - PCRE2 has this "properly" fixed).
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1636 2f5784b3-3f2a-0410-8824-cb99058d5e15
+
+Petr PÃsaÅ™: Ported to 8.38.
+
+diff --git a/pcre_compile.c b/pcre_compile.c
+index 5019854..4ffea0c 100644
+--- a/pcre_compile.c
++++ b/pcre_compile.c
+@@ -7311,7 +7311,12 @@ for (;; ptr++)
+ so far in order to get the number. If the name is not found, leave
+ the value of recno as 0 for a forward reference. */
+
+- else
++ /* This patch (removing "else") fixes a problem when a reference is
++ to multiple identically named nested groups from within the nest.
++ Once again, it is not the "proper" fix, and it results in an
++ over-allocation of memory. */
++
++ /* else */
+ {
+ ng = cd->named_groups;
+ for (i = 0; i < cd->names_found; i++, ng++)
+diff --git a/testdata/testinput2 b/testdata/testinput2
+index 086e0f4..c805f5f 100644
+--- a/testdata/testinput2
++++ b/testdata/testinput2
+@@ -4239,4 +4239,6 @@ backtracking verbs. --/
+ 9010
+ abcd
+
++/((?J)(?'R'(?'R'(?'R'(?'R'(?'R'(?|(\k'R'))))))))/
++
+ /-- End of testinput2 --/
+diff --git a/testdata/testoutput2 b/testdata/testoutput2
+index d414a72..800a72f 100644
+--- a/testdata/testoutput2
++++ b/testdata/testoutput2
+@@ -14665,4 +14665,6 @@ Start of matched string is beyond its end - displaying from end to start.
+ 0 ^ 0
+ No match
+
++/((?J)(?'R'(?'R'(?'R'(?'R'(?'R'(?|(\k'R'))))))))/
++
+ /-- End of testinput2 --/
+--
+2.5.0
+
+From 0fc2edb79b3815c6511fd75c36a57893e4acaee6 Mon Sep 17 00:00:00 2001
+From: ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>
+Date: Sat, 27 Feb 2016 17:55:24 +0000
+Subject: [PATCH] Fix pcretest loop for global matching with an ovector size
+ less than 2.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1637 2f5784b3-3f2a-0410-8824-cb99058d5e15
+
+Petr PÃsaÅ™: Ported to 8.38.
+
+diff --git a/pcretest.c b/pcretest.c
+index 63869fd..78ef517 100644
+--- a/pcretest.c
++++ b/pcretest.c
+@@ -5617,6 +5617,12 @@ while (!done)
+ break;
+ }
+
++ if (use_size_offsets < 2)
++ {
++ fprintf(outfile, "Cannot do global matching with an ovector size < 2\n");
++ break;
++ }
++
+ /* If we have matched an empty string, first check to see if we are at
+ the end of the subject. If so, the /g loop is over. Otherwise, mimic what
+ Perl's /g options does. This turns out to be rather cunning. First we set
+--
+2.5.0
+
+From b3db1b7de5cfaa026ec2bc4a393129461a0f5c57 Mon Sep 17 00:00:00 2001
+From: ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>
+Date: Sat, 27 Feb 2016 18:44:41 +0000
+Subject: [PATCH] Fix non-diagnosis of missing assertion after (?(?C).
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1638 2f5784b3-3f2a-0410-8824-cb99058d5e15
+
+Petr PÃsaÅ™: Ported to 8.38.
+
+diff --git a/pcre_compile.c b/pcre_compile.c
+index 4ffea0c..254c629 100644
+--- a/pcre_compile.c
++++ b/pcre_compile.c
+@@ -485,7 +485,7 @@ static const char error_texts[] =
+ "lookbehind assertion is not fixed length\0"
+ "malformed number or name after (?(\0"
+ "conditional group contains more than two branches\0"
+- "assertion expected after (?(\0"
++ "assertion expected after (?( or (?(?C)\0"
+ "(?R or (?[+-]digits must be followed by )\0"
+ /* 30 */
+ "unknown POSIX class name\0"
+@@ -6771,6 +6771,15 @@ for (;; ptr++)
+ for (i = 3;; i++) if (!IS_DIGIT(ptr[i])) break;
+ if (ptr[i] == CHAR_RIGHT_PARENTHESIS)
+ tempptr += i + 1;
++
++ /* tempptr should now be pointing to the opening parenthesis of the
++ assertion condition. */
++
++ if (*tempptr != CHAR_LEFT_PARENTHESIS)
++ {
++ *errorcodeptr = ERR28;
++ goto FAILED;
++ }
+ }
+
+ /* For conditions that are assertions, check the syntax, and then exit
+diff --git a/testdata/testinput2 b/testdata/testinput2
+index c805f5f..75e402e 100644
+--- a/testdata/testinput2
++++ b/testdata/testinput2
+@@ -4241,4 +4241,6 @@ backtracking verbs. --/
+
+ /((?J)(?'R'(?'R'(?'R'(?'R'(?'R'(?|(\k'R'))))))))/
+
++/\N(?(?C)0?!.)*/
++
+ /-- End of testinput2 --/
+diff --git a/testdata/testoutput2 b/testdata/testoutput2
+index 800a72f..5e88d1a 100644
+--- a/testdata/testoutput2
++++ b/testdata/testoutput2
+@@ -555,13 +555,13 @@ Failed: malformed number or name after (?( at offset 4
+ Failed: malformed number or name after (?( at offset 4
+
+ /(?(?i))/
+-Failed: assertion expected after (?( at offset 3
++Failed: assertion expected after (?( or (?(?C) at offset 3
+
+ /(?(abc))/
+ Failed: reference to non-existent subpattern at offset 7
+
+ /(?(?<ab))/
+-Failed: assertion expected after (?( at offset 3
++Failed: assertion expected after (?( or (?(?C) at offset 3
+
+ /((?s)blah)\s+\1/I
+ Capturing subpattern count = 1
+@@ -7870,7 +7870,7 @@ No match
+ Failed: malformed number or name after (?( at offset 6
+
+ /(?(''))/
+-Failed: assertion expected after (?( at offset 4
++Failed: assertion expected after (?( or (?(?C) at offset 4
+
+ /(?('R')stuff)/
+ Failed: reference to non-existent subpattern at offset 7
+@@ -14346,7 +14346,7 @@ No match
+ "((?2)+)((?1))"
+
+ "(?(?<E>.*!.*)?)"
+-Failed: assertion expected after (?( at offset 3
++Failed: assertion expected after (?( or (?(?C) at offset 3
+
+ "X((?2)()*+){2}+"BZ
+ ------------------------------------------------------------------
+@@ -14667,4 +14667,7 @@ No match
+
+ /((?J)(?'R'(?'R'(?'R'(?'R'(?'R'(?|(\k'R'))))))))/
+
++/\N(?(?C)0?!.)*/
++Failed: assertion expected after (?( or (?(?C) at offset 4
++
+ /-- End of testinput2 --/
+--
+2.5.0
+
--- /dev/null
+--- setup.py~ 2008-04-22 17:00:45.000000000 +0300
++++ setup.py 2008-07-03 21:53:36.000000000 +0300
+@@ -97,8 +97,7 @@
+ else:
+ extra_compile_args.append(e)
+ libs = split_quoted(
+- os.popen("'%s' --libs" % CURL_CONFIG).read()+\
+- os.popen("'%s' --static-libs" % CURL_CONFIG).read())
++ os.popen("'%s' --libs" % CURL_CONFIG).read())
+ for e in libs:
+ if e[:2] == "-l":
+ libraries.append(e[2:])
--- /dev/null
+Submitted By: Tushar Teredesai <tushar@linuxfromscratch.org>
+Date: 2003-10-04
+Initial Package Version: 7.6
+Origin: http://archives.linuxfromscratch.org/mail-archives/blfs-dev/2003-January/001960.html
+Description: The patch was created from the tcp_wrappers modified package by Mark Heerdink.
+This patch provides the following improvements:
+ * Install libwrap.so along with libwrap.a.
+ * Create an install target for tcp_wrappers.
+ * Compilation and security fixes.
+ * Documentation fixes.
+diff -Naur tcp_wrappers_7.6/Makefile tcp_wrappers_7.6.gimli/Makefile
+--- tcp_wrappers_7.6/Makefile 1997-03-21 12:27:21.000000000 -0600
++++ tcp_wrappers_7.6.gimli/Makefile 2002-07-15 16:07:21.000000000 -0500
+@@ -1,5 +1,10 @@
++GLIBC=$(shell grep -s -c __GLIBC__ /usr/include/features.h)
++
+ # @(#) Makefile 1.23 97/03/21 19:27:20
+
++# unset the HOSTNAME environment variable
++HOSTNAME =
++
+ what:
+ @echo
+ @echo "Usage: edit the REAL_DAEMON_DIR definition in the Makefile then:"
+@@ -19,7 +24,7 @@
+ @echo " generic (most bsd-ish systems with sys5 compatibility)"
+ @echo " 386bsd aix alpha apollo bsdos convex-ultranet dell-gcc dgux dgux543"
+ @echo " dynix epix esix freebsd hpux irix4 irix5 irix6 isc iunix"
+- @echo " linux machten mips(untested) ncrsvr4 netbsd next osf power_unix_211"
++ @echo " linux gnu machten mips(untested) ncrsvr4 netbsd next osf power_unix_211"
+ @echo " ptx-2.x ptx-generic pyramid sco sco-nis sco-od2 sco-os5 sinix sunos4"
+ @echo " sunos40 sunos5 sysv4 tandem ultrix unicos7 unicos8 unixware1 unixware2"
+ @echo " uts215 uxp"
+@@ -43,8 +48,8 @@
+ # Ultrix 4.x SunOS 4.x ConvexOS 10.x Dynix/ptx
+ #REAL_DAEMON_DIR=/usr/etc
+ #
+-# SysV.4 Solaris 2.x OSF AIX
+-#REAL_DAEMON_DIR=/usr/sbin
++# SysV.4 Solaris 2.x OSF AIX Linux
++REAL_DAEMON_DIR=/usr/sbin
+ #
+ # BSD 4.4
+ #REAL_DAEMON_DIR=/usr/libexec
+@@ -141,10 +146,21 @@
+ LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ= NETGROUP= TLI= \
+ EXTRA_CFLAGS=-DSYS_ERRLIST_DEFINED VSYSLOG= all
+
++ifneq ($(GLIBC),0)
++MYLIB=-lnsl
++endif
++
+ linux:
+ @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
+- LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ=setenv.o \
+- NETGROUP= TLI= EXTRA_CFLAGS="-DBROKEN_SO_LINGER" all
++ LIBS=$(MYLIB) RANLIB=ranlib ARFLAGS=rv AUX_OBJ=weak_symbols.o \
++ NETGROUP=-DNETGROUP TLI= VSYSLOG= BUGS= all \
++ EXTRA_CFLAGS="-DSYS_ERRLIST_DEFINED -DHAVE_WEAKSYMS -D_REENTRANT"
++
++gnu:
++ @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
++ LIBS=$(MYLIB) RANLIB=ranlib ARFLAGS=rv AUX_OBJ=weak_symbols.o \
++ NETGROUP=-DNETGROUP TLI= VSYSLOG= BUGS= all \
++ EXTRA_CFLAGS="-DHAVE_STRERROR -DHAVE_WEAKSYMS -D_REENTRANT"
+
+ # This is good for many SYSV+BSD hybrids with NIS, probably also for HP-UX 7.x.
+ hpux hpux8 hpux9 hpux10:
+@@ -391,7 +407,7 @@
+ # the ones provided with this source distribution. The environ.c module
+ # implements setenv(), getenv(), and putenv().
+
+-AUX_OBJ= setenv.o
++#AUX_OBJ= setenv.o
+ #AUX_OBJ= environ.o
+ #AUX_OBJ= environ.o strcasecmp.o
+
+@@ -454,7 +470,8 @@
+ # host name aliases. Compile with -DSOLARIS_24_GETHOSTBYNAME_BUG to work
+ # around this. The workaround does no harm on other Solaris versions.
+
+-BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS -DLIBC_CALLS_STRTOK
++BUGS =
++#BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS -DLIBC_CALLS_STRTOK
+ #BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS -DINET_ADDR_BUG
+ #BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS -DSOLARIS_24_GETHOSTBYNAME_BUG
+
+@@ -464,7 +481,7 @@
+ # If your system supports NIS or YP-style netgroups, enable the following
+ # macro definition. Netgroups are used only for host access control.
+ #
+-#NETGROUP= -DNETGROUP
++NETGROUP= -DNETGROUP
+
+ ###############################################################
+ # System dependencies: whether or not your system has vsyslog()
+@@ -491,7 +508,7 @@
+ # Uncomment the next definition to turn on the language extensions
+ # (examples: allow, deny, banners, twist and spawn).
+ #
+-#STYLE = -DPROCESS_OPTIONS # Enable language extensions.
++STYLE = -DPROCESS_OPTIONS # Enable language extensions.
+
+ ################################################################
+ # Optional: Changing the default disposition of logfile records
+@@ -514,7 +531,7 @@
+ #
+ # The LOG_XXX names below are taken from the /usr/include/syslog.h file.
+
+-FACILITY= LOG_MAIL # LOG_MAIL is what most sendmail daemons use
++FACILITY= LOG_DAEMON # LOG_MAIL is what most sendmail daemons use
+
+ # The syslog priority at which successful connections are logged.
+
+@@ -610,7 +627,7 @@
+ # Paranoid mode implies hostname lookup. In order to disable hostname
+ # lookups altogether, see the next section.
+
+-PARANOID= -DPARANOID
++#PARANOID= -DPARANOID
+
+ ########################################
+ # Optional: turning off hostname lookups
+@@ -623,7 +640,7 @@
+ # In order to perform selective hostname lookups, disable paranoid
+ # mode (see previous section) and comment out the following definition.
+
+-HOSTNAME= -DALWAYS_HOSTNAME
++#HOSTNAME= -DALWAYS_HOSTNAME
+
+ #############################################
+ # Optional: Turning on host ADDRESS checking
+@@ -649,28 +666,46 @@
+ # source-routed traffic in the kernel. Examples: 4.4BSD derivatives,
+ # Solaris 2.x, and Linux. See your system documentation for details.
+ #
+-# KILL_OPT= -DKILL_IP_OPTIONS
++KILL_OPT= -DKILL_IP_OPTIONS
+
+ ## End configuration options
+ ############################
+
+ # Protection against weird shells or weird make programs.
+
++CC = gcc
+ SHELL = /bin/sh
+-.c.o:; $(CC) $(CFLAGS) -c $*.c
++.c.o:; $(CC) $(CFLAGS) -o $*.o -c $*.c
++
++SOMAJOR = 0
++SOMINOR = 7.6
++
++LIB = libwrap.a
++SHLIB = shared/libwrap.so.$(SOMAJOR).$(SOMINOR)
++SHLIBSOMAJ= shared/libwrap.so.$(SOMAJOR)
++SHLIBSO = shared/libwrap.so
++SHLIBFLAGS = -Lshared -lwrap
+
+-CFLAGS = -O -DFACILITY=$(FACILITY) $(ACCESS) $(PARANOID) $(NETGROUP) \
++shared/%.o: %.c
++ $(CC) $(CFLAGS) $(SHCFLAGS) -c $< -o $@
++
++CFLAGS = -O2 -DFACILITY=$(FACILITY) $(ACCESS) $(PARANOID) $(NETGROUP) \
+ $(BUGS) $(SYSTYPE) $(AUTH) $(UMASK) \
+ -DREAL_DAEMON_DIR=\"$(REAL_DAEMON_DIR)\" $(STYLE) $(KILL_OPT) \
+ -DSEVERITY=$(SEVERITY) -DRFC931_TIMEOUT=$(RFC931_TIMEOUT) \
+ $(UCHAR) $(TABLES) $(STRINGS) $(TLI) $(EXTRA_CFLAGS) $(DOT) \
+ $(VSYSLOG) $(HOSTNAME)
+
++SHLINKFLAGS = -shared -Xlinker -soname -Xlinker libwrap.so.$(SOMAJOR) -lc $(LIBS)
++SHCFLAGS = -fPIC -shared -D_REENTRANT
++
+ LIB_OBJ= hosts_access.o options.o shell_cmd.o rfc931.o eval.o \
+ hosts_ctl.o refuse.o percent_x.o clean_exit.o $(AUX_OBJ) \
+ $(FROM_OBJ) fix_options.o socket.o tli.o workarounds.o \
+ update.o misc.o diag.o percent_m.o myvsyslog.o
+
++SHLIB_OBJ= $(addprefix shared/, $(LIB_OBJ));
++
+ FROM_OBJ= fromhost.o
+
+ KIT = README miscd.c tcpd.c fromhost.c hosts_access.c shell_cmd.c \
+@@ -684,46 +719,80 @@
+ refuse.c tcpdchk.8 setenv.c inetcf.c inetcf.h scaffold.c \
+ scaffold.h tcpdmatch.8 README.NIS
+
+-LIB = libwrap.a
+-
+-all other: config-check tcpd tcpdmatch try-from safe_finger tcpdchk
++all other: config-check tcpd tcpdmatch try-from safe_finger tcpdchk $(LIB)
+
+ # Invalidate all object files when the compiler options (CFLAGS) have changed.
+
+ config-check:
+ @set +e; test -n "$(REAL_DAEMON_DIR)" || { make; exit 1; }
+- @set +e; echo $(CFLAGS) >/tmp/cflags.$$$$ ; \
+- if cmp cflags /tmp/cflags.$$$$ ; \
+- then rm /tmp/cflags.$$$$ ; \
+- else mv /tmp/cflags.$$$$ cflags ; \
++ @set +e; echo $(CFLAGS) >cflags.new ; \
++ if cmp cflags cflags.new ; \
++ then rm cflags.new ; \
++ else mv cflags.new cflags ; \
+ fi >/dev/null 2>/dev/null
++ @if [ ! -d shared ]; then mkdir shared; fi
+
+ $(LIB): $(LIB_OBJ)
+ rm -f $(LIB)
+ $(AR) $(ARFLAGS) $(LIB) $(LIB_OBJ)
+ -$(RANLIB) $(LIB)
+
+-tcpd: tcpd.o $(LIB)
+- $(CC) $(CFLAGS) -o $@ tcpd.o $(LIB) $(LIBS)
++$(SHLIB): $(SHLIB_OBJ)
++ rm -f $(SHLIB)
++ $(CC) -o $(SHLIB) $(SHLINKFLAGS) $(SHLIB_OBJ)
++ ln -s $(notdir $(SHLIB)) $(SHLIBSOMAJ)
++ ln -s $(notdir $(SHLIBSOMAJ)) $(SHLIBSO)
++
++tcpd: tcpd.o $(SHLIB)
++ $(CC) $(CFLAGS) -o $@ tcpd.o $(SHLIBFLAGS)
+
+-miscd: miscd.o $(LIB)
+- $(CC) $(CFLAGS) -o $@ miscd.o $(LIB) $(LIBS)
++miscd: miscd.o $(SHLIB)
++ $(CC) $(CFLAGS) -o $@ miscd.o $(SHLIBFLAGS)
+
+-safe_finger: safe_finger.o $(LIB)
+- $(CC) $(CFLAGS) -o $@ safe_finger.o $(LIB) $(LIBS)
++safe_finger: safe_finger.o $(SHLIB)
++ $(CC) $(CFLAGS) -o $@ safe_finger.o $(SHLIBFLAGS)
+
+ TCPDMATCH_OBJ = tcpdmatch.o fakelog.o inetcf.o scaffold.o
+
+-tcpdmatch: $(TCPDMATCH_OBJ) $(LIB)
+- $(CC) $(CFLAGS) -o $@ $(TCPDMATCH_OBJ) $(LIB) $(LIBS)
++tcpdmatch: $(TCPDMATCH_OBJ) $(SHLIB)
++ $(CC) $(CFLAGS) -o $@ $(TCPDMATCH_OBJ) $(SHLIBFLAGS)
+
+-try-from: try-from.o fakelog.o $(LIB)
+- $(CC) $(CFLAGS) -o $@ try-from.o fakelog.o $(LIB) $(LIBS)
++try-from: try-from.o fakelog.o $(SHLIB)
++ $(CC) $(CFLAGS) -o $@ try-from.o fakelog.o $(SHLIBFLAGS)
+
+ TCPDCHK_OBJ = tcpdchk.o fakelog.o inetcf.o scaffold.o
+
+-tcpdchk: $(TCPDCHK_OBJ) $(LIB)
+- $(CC) $(CFLAGS) -o $@ $(TCPDCHK_OBJ) $(LIB) $(LIBS)
++tcpdchk: $(TCPDCHK_OBJ) $(SHLIB)
++ $(CC) $(CFLAGS) -o $@ $(TCPDCHK_OBJ) $(SHLIBFLAGS)
++
++install: install-lib install-bin install-dev
++
++install-lib:
++ install -o root -g root -m 0755 $(SHLIB) ${DESTDIR}/usr/lib/
++ ln -sf $(notdir $(SHLIB)) ${DESTDIR}/usr/lib/$(notdir $(SHLIBSOMAJ))
++ ln -sf $(notdir $(SHLIBSOMAJ)) ${DESTDIR}/usr/lib/$(notdir $(SHLIBSO))
++
++install-bin:
++ install -o root -g root -m 0755 tcpd ${DESTDIR}/usr/sbin/
++ install -o root -g root -m 0755 tcpdchk ${DESTDIR}/usr/sbin/
++ install -o root -g root -m 0755 tcpdmatch ${DESTDIR}/usr/sbin/
++ install -o root -g root -m 0755 try-from ${DESTDIR}/usr/sbin/
++ install -o root -g root -m 0755 safe_finger ${DESTDIR}/usr/sbin/
++ install -o root -g root -m 0644 tcpd.8 ${DESTDIR}/usr/share/man/man8/
++ install -o root -g root -m 0644 tcpdchk.8 ${DESTDIR}/usr/share/man/man8/
++ install -o root -g root -m 0644 try-from.8 ${DESTDIR}/usr/share/man/man8/
++ install -o root -g root -m 0644 tcpdmatch.8 ${DESTDIR}/usr/share/man/man8/
++ install -o root -g root -m 0644 safe_finger.8 ${DESTDIR}/usr/share/man/man8/
++ install -o root -g root -m 0644 hosts_access.5 ${DESTDIR}/usr/share/man/man5/
++ install -o root -g root -m 0644 hosts_options.5 ${DESTDIR}/usr/share/man/man5/
++
++install-dev:
++ install -o root -g root -m 0644 hosts_access.3 ${DESTDIR}/usr/share/man/man3/
++ install -o root -g root -m 0644 tcpd.h ${DESTDIR}/usr/include/
++ install -o root -g root -m 0644 $(LIB) ${DESTDIR}/usr/lib/
++ ln -sf hosts_access.3 ${DESTDIR}/usr/share/man/man3/hosts_ctl.3
++ ln -sf hosts_access.3 ${DESTDIR}/usr/share/man/man3/request_init.3
++ ln -sf hosts_access.3 ${DESTDIR}/usr/share/man/man3/request_set.3
+
+ shar: $(KIT)
+ @shar $(KIT)
+@@ -739,7 +808,8 @@
+
+ clean:
+ rm -f tcpd miscd safe_finger tcpdmatch tcpdchk try-from *.[oa] core \
+- cflags
++ cflags libwrap*.so*
++ rm -rf shared
+
+ tidy: clean
+ chmod -R a+r .
+@@ -885,5 +955,6 @@
+ update.o: mystdarg.h
+ update.o: tcpd.h
+ vfprintf.o: cflags
++weak_symbols.o: tcpd.h
+ workarounds.o: cflags
+ workarounds.o: tcpd.h
+diff -Naur tcp_wrappers_7.6/fix_options.c tcp_wrappers_7.6.gimli/fix_options.c
+--- tcp_wrappers_7.6/fix_options.c 1997-04-07 19:29:19.000000000 -0500
++++ tcp_wrappers_7.6.gimli/fix_options.c 2002-01-07 08:50:19.000000000 -0600
+@@ -35,7 +35,12 @@
+ #ifdef IP_OPTIONS
+ unsigned char optbuf[BUFFER_SIZE / 3], *cp;
+ char lbuf[BUFFER_SIZE], *lp;
++#if !defined(__GLIBC__)
+ int optsize = sizeof(optbuf), ipproto;
++#else /* __GLIBC__ */
++ size_t optsize = sizeof(optbuf);
++ int ipproto;
++#endif /* __GLIBC__ */
+ struct protoent *ip;
+ int fd = request->fd;
+ unsigned int opt;
+diff -Naur tcp_wrappers_7.6/hosts_access.3 tcp_wrappers_7.6.gimli/hosts_access.3
+--- tcp_wrappers_7.6/hosts_access.3 1996-02-11 10:01:27.000000000 -0600
++++ tcp_wrappers_7.6.gimli/hosts_access.3 2002-01-07 08:50:19.000000000 -0600
+@@ -3,7 +3,7 @@
+ hosts_access, hosts_ctl, request_init, request_set \- access control library
+ .SH SYNOPSIS
+ .nf
+-#include "tcpd.h"
++#include <tcpd.h>
+
+ extern int allow_severity;
+ extern int deny_severity;
+diff -Naur tcp_wrappers_7.6/hosts_access.5 tcp_wrappers_7.6.gimli/hosts_access.5
+--- tcp_wrappers_7.6/hosts_access.5 1995-01-30 12:51:47.000000000 -0600
++++ tcp_wrappers_7.6.gimli/hosts_access.5 2002-01-07 08:50:19.000000000 -0600
+@@ -8,9 +8,9 @@
+ impatient reader is encouraged to skip to the EXAMPLES section for a
+ quick introduction.
+ .PP
+-An extended version of the access control language is described in the
+-\fIhosts_options\fR(5) document. The extensions are turned on at
+-program build time by building with -DPROCESS_OPTIONS.
++The extended version of the access control language is described in the
++\fIhosts_options\fR(5) document. \fBNote that this language supersedes
++the meaning of \fIshell_command\fB as documented below.\fR
+ .PP
+ In the following text, \fIdaemon\fR is the the process name of a
+ network daemon process, and \fIclient\fR is the name and/or address of
+@@ -40,7 +40,7 @@
+ character. This permits you to break up long lines so that they are
+ easier to edit.
+ .IP \(bu
+-Blank lines or lines that begin with a `#\' character are ignored.
++Blank lines or lines that begin with a `#' character are ignored.
+ This permits you to insert comments and whitespace so that the tables
+ are easier to read.
+ .IP \(bu
+@@ -69,26 +69,33 @@
+ .SH PATTERNS
+ The access control language implements the following patterns:
+ .IP \(bu
+-A string that begins with a `.\' character. A host name is matched if
++A string that begins with a `.' character. A host name is matched if
+ the last components of its name match the specified pattern. For
+-example, the pattern `.tue.nl\' matches the host name
+-`wzv.win.tue.nl\'.
++example, the pattern `.tue.nl' matches the host name
++`wzv.win.tue.nl'.
+ .IP \(bu
+-A string that ends with a `.\' character. A host address is matched if
++A string that ends with a `.' character. A host address is matched if
+ its first numeric fields match the given string. For example, the
+-pattern `131.155.\' matches the address of (almost) every host on the
++pattern `131.155.' matches the address of (almost) every host on the
+ Eind\%hoven University network (131.155.x.x).
+ .IP \(bu
+-A string that begins with an `@\' character is treated as an NIS
++A string that begins with an `@' character is treated as an NIS
+ (formerly YP) netgroup name. A host name is matched if it is a host
+ member of the specified netgroup. Netgroup matches are not supported
+ for daemon process names or for client user names.
+ .IP \(bu
+-An expression of the form `n.n.n.n/m.m.m.m\' is interpreted as a
+-`net/mask\' pair. A host address is matched if `net\' is equal to the
+-bitwise AND of the address and the `mask\'. For example, the net/mask
+-pattern `131.155.72.0/255.255.254.0\' matches every address in the
+-range `131.155.72.0\' through `131.155.73.255\'.
++An expression of the form `n.n.n.n/m.m.m.m' is interpreted as a
++`net/mask' pair. A host address is matched if `net' is equal to the
++bitwise AND of the address and the `mask'. For example, the net/mask
++pattern `131.155.72.0/255.255.254.0' matches every address in the
++range `131.155.72.0' through `131.155.73.255'.
++.IP \(bu
++A string that begins with a `/' character is treated as a file
++name. A host name or address is matched if it matches any host name
++or address pattern listed in the named file. The file format is
++zero or more lines with zero or more host name or address patterns
++separated by whitespace. A file name pattern can be used anywhere
++a host name or address pattern can be used.
+ .SH WILDCARDS
+ The access control language supports explicit wildcards:
+ .IP ALL
+@@ -115,19 +122,19 @@
+ .ne 6
+ .SH OPERATORS
+ .IP EXCEPT
+-Intended use is of the form: `list_1 EXCEPT list_2\'; this construct
++Intended use is of the form: `list_1 EXCEPT list_2'; this construct
+ matches anything that matches \fIlist_1\fR unless it matches
+ \fIlist_2\fR. The EXCEPT operator can be used in daemon_lists and in
+ client_lists. The EXCEPT operator can be nested: if the control
+-language would permit the use of parentheses, `a EXCEPT b EXCEPT c\'
+-would parse as `(a EXCEPT (b EXCEPT c))\'.
++language would permit the use of parentheses, `a EXCEPT b EXCEPT c'
++would parse as `(a EXCEPT (b EXCEPT c))'.
+ .br
+ .ne 6
+ .SH SHELL COMMANDS
+ If the first-matched access control rule contains a shell command, that
+ command is subjected to %<letter> substitutions (see next section).
+ The result is executed by a \fI/bin/sh\fR child process with standard
+-input, output and error connected to \fI/dev/null\fR. Specify an `&\'
++input, output and error connected to \fI/dev/null\fR. Specify an `&'
+ at the end of the command if you do not want to wait until it has
+ completed.
+ .PP
+@@ -159,7 +166,7 @@
+ .IP %u
+ The client user name (or "unknown").
+ .IP %%
+-Expands to a single `%\' character.
++Expands to a single `%' character.
+ .PP
+ Characters in % expansions that may confuse the shell are replaced by
+ underscores.
+@@ -243,9 +250,9 @@
+ less trustworthy. It is possible for an intruder to spoof both the
+ client connection and the IDENT lookup, although doing so is much
+ harder than spoofing just a client connection. It may also be that
+-the client\'s IDENT server is lying.
++the client's IDENT server is lying.
+ .PP
+-Note: IDENT lookups don\'t work with UDP services.
++Note: IDENT lookups don't work with UDP services.
+ .SH EXAMPLES
+ The language is flexible enough that different types of access control
+ policy can be expressed with a minimum of fuss. Although the language
+@@ -285,7 +292,7 @@
+ .br
+ ALL: .foobar.edu EXCEPT terminalserver.foobar.edu
+ .PP
+-The first rule permits access from hosts in the local domain (no `.\'
++The first rule permits access from hosts in the local domain (no `.'
+ in the host name) and from members of the \fIsome_netgroup\fP
+ netgroup. The second rule permits access from all hosts in the
+ \fIfoobar.edu\fP domain (notice the leading dot), with the exception of
+@@ -322,8 +329,8 @@
+ /etc/hosts.deny:
+ .in +3
+ .nf
+-in.tftpd: ALL: (/some/where/safe_finger -l @%h | \\
+- /usr/ucb/mail -s %d-%h root) &
++in.tftpd: ALL: (/usr/sbin/safe_finger -l @%h | \\
++ /usr/bin/mail -s %d-%h root) &
+ .fi
+ .PP
+ The safe_finger command comes with the tcpd wrapper and should be
+@@ -349,7 +356,7 @@
+ capacity of an internal buffer; when an access control rule is not
+ terminated by a newline character; when the result of %<letter>
+ expansion would overflow an internal buffer; when a system call fails
+-that shouldn\'t. All problems are reported via the syslog daemon.
++that shouldn't. All problems are reported via the syslog daemon.
+ .SH FILES
+ .na
+ .nf
+diff -Naur tcp_wrappers_7.6/hosts_access.c tcp_wrappers_7.6.gimli/hosts_access.c
+--- tcp_wrappers_7.6/hosts_access.c 1997-02-11 19:13:23.000000000 -0600
++++ tcp_wrappers_7.6.gimli/hosts_access.c 2002-01-07 08:50:19.000000000 -0600
+@@ -240,6 +240,26 @@
+ }
+ }
+
++/* hostfile_match - look up host patterns from file */
++
++static int hostfile_match(path, host)
++char *path;
++struct hosts_info *host;
++{
++ char tok[BUFSIZ];
++ int match = NO;
++ FILE *fp;
++
++ if ((fp = fopen(path, "r")) != 0) {
++ while (fscanf(fp, "%s", tok) == 1 && !(match = host_match(tok, host)))
++ /* void */ ;
++ fclose(fp);
++ } else if (errno != ENOENT) {
++ tcpd_warn("open %s: %m", path);
++ }
++ return (match);
++}
++
+ /* host_match - match host name and/or address against pattern */
+
+ static int host_match(tok, host)
+@@ -267,6 +287,8 @@
+ tcpd_warn("netgroup support is disabled"); /* not tcpd_jump() */
+ return (NO);
+ #endif
++ } else if (tok[0] == '/') { /* /file hack */
++ return (hostfile_match(tok, host));
+ } else if (STR_EQ(tok, "KNOWN")) { /* check address and name */
+ char *name = eval_hostname(host);
+ return (STR_NE(eval_hostaddr(host), unknown) && HOSTNAME_KNOWN(name));
+diff -Naur tcp_wrappers_7.6/hosts_options.5 tcp_wrappers_7.6.gimli/hosts_options.5
+--- tcp_wrappers_7.6/hosts_options.5 1994-12-28 10:42:29.000000000 -0600
++++ tcp_wrappers_7.6.gimli/hosts_options.5 2002-01-07 08:50:19.000000000 -0600
+@@ -58,12 +58,12 @@
+ Execute, in a child process, the specified shell command, after
+ performing the %<letter> expansions described in the hosts_access(5)
+ manual page. The command is executed with stdin, stdout and stderr
+-connected to the null device, so that it won\'t mess up the
++connected to the null device, so that it won't mess up the
+ conversation with the client host. Example:
+ .sp
+ .nf
+ .ti +3
+-spawn (/some/where/safe_finger -l @%h | /usr/ucb/mail root) &
++spawn (/usr/sbin/safe_finger -l @%h | /usr/bin/mail root) &
+ .fi
+ .sp
+ executes, in a background child process, the shell command "safe_finger
+diff -Naur tcp_wrappers_7.6/options.c tcp_wrappers_7.6.gimli/options.c
+--- tcp_wrappers_7.6/options.c 1996-02-11 10:01:32.000000000 -0600
++++ tcp_wrappers_7.6.gimli/options.c 2002-01-07 08:50:19.000000000 -0600
+@@ -473,6 +473,9 @@
+ #ifdef LOG_CRON
+ "cron", LOG_CRON,
+ #endif
++#ifdef LOG_FTP
++ "ftp", LOG_FTP,
++#endif
+ #ifdef LOG_LOCAL0
+ "local0", LOG_LOCAL0,
+ #endif
+diff -Naur tcp_wrappers_7.6/percent_m.c tcp_wrappers_7.6.gimli/percent_m.c
+--- tcp_wrappers_7.6/percent_m.c 1994-12-28 10:42:37.000000000 -0600
++++ tcp_wrappers_7.6.gimli/percent_m.c 2002-01-07 08:50:19.000000000 -0600
+@@ -13,7 +13,7 @@
+ #include <string.h>
+
+ extern int errno;
+-#ifndef SYS_ERRLIST_DEFINED
++#if !defined(SYS_ERRLIST_DEFINED) && !defined(HAVE_STRERROR)
+ extern char *sys_errlist[];
+ extern int sys_nerr;
+ #endif
+@@ -29,11 +29,15 @@
+
+ while (*bp = *cp)
+ if (*cp == '%' && cp[1] == 'm') {
++#ifdef HAVE_STRERROR
++ strcpy(bp, strerror(errno));
++#else
+ if (errno < sys_nerr && errno > 0) {
+ strcpy(bp, sys_errlist[errno]);
+ } else {
+ sprintf(bp, "Unknown error %d", errno);
+ }
++#endif
+ bp += strlen(bp);
+ cp += 2;
+ } else {
+diff -Naur tcp_wrappers_7.6/rfc931.c tcp_wrappers_7.6.gimli/rfc931.c
+--- tcp_wrappers_7.6/rfc931.c 1995-01-02 09:11:34.000000000 -0600
++++ tcp_wrappers_7.6.gimli/rfc931.c 2002-01-07 08:50:19.000000000 -0600
+@@ -33,7 +33,7 @@
+
+ int rfc931_timeout = RFC931_TIMEOUT;/* Global so it can be changed */
+
+-static jmp_buf timebuf;
++static sigjmp_buf timebuf;
+
+ /* fsocket - open stdio stream on top of socket */
+
+@@ -62,7 +62,7 @@
+ static void timeout(sig)
+ int sig;
+ {
+- longjmp(timebuf, sig);
++ siglongjmp(timebuf, sig);
+ }
+
+ /* rfc931 - return remote user name, given socket structures */
+@@ -99,7 +99,7 @@
+ * Set up a timer so we won't get stuck while waiting for the server.
+ */
+
+- if (setjmp(timebuf) == 0) {
++ if (sigsetjmp(timebuf,1) == 0) {
+ signal(SIGALRM, timeout);
+ alarm(rfc931_timeout);
+
+diff -Naur tcp_wrappers_7.6/safe_finger.8 tcp_wrappers_7.6.gimli/safe_finger.8
+--- tcp_wrappers_7.6/safe_finger.8 1969-12-31 18:00:00.000000000 -0600
++++ tcp_wrappers_7.6.gimli/safe_finger.8 2002-01-07 08:50:19.000000000 -0600
+@@ -0,0 +1,34 @@
++.TH SAFE_FINGER 8 "21th June 1997" Linux "Linux Programmer's Manual"
++.SH NAME
++safe_finger \- finger client wrapper that protects against nasty stuff
++from finger servers
++.SH SYNOPSIS
++.B safe_finger [finger_options]
++.SH DESCRIPTION
++The
++.B safe_finger
++command protects against nasty stuff from finger servers. Use this
++program for automatic reverse finger probes from the
++.B tcp_wrapper
++.B (tcpd)
++, not the raw finger command. The
++.B safe_finger
++command makes sure that the finger client is not run with root
++privileges. It also runs the finger client with a defined PATH
++environment.
++.B safe_finger
++will also protect you from problems caused by the output of some
++finger servers. The problem: some programs may react to stuff in
++the first column. Other programs may get upset by thrash anywhere
++on a line. File systems may fill up as the finger server keeps
++sending data. Text editors may bomb out on extremely long lines.
++The finger server may take forever because it is somehow wedged.
++.B safe_finger
++takes care of all this badness.
++.SH SEE ALSO
++.BR hosts_access (5),
++.BR hosts_options (5),
++.BR tcpd (8)
++.SH AUTHOR
++Wietse Venema, Eindhoven University of Technology, The Netherlands.
++
+diff -Naur tcp_wrappers_7.6/safe_finger.c tcp_wrappers_7.6.gimli/safe_finger.c
+--- tcp_wrappers_7.6/safe_finger.c 1994-12-28 10:42:42.000000000 -0600
++++ tcp_wrappers_7.6.gimli/safe_finger.c 2002-01-07 08:50:19.000000000 -0600
+@@ -26,21 +26,24 @@
+ #include <stdio.h>
+ #include <ctype.h>
+ #include <pwd.h>
++#include <syslog.h>
+
+ extern void exit();
+
+ /* Local stuff */
+
+-char path[] = "PATH=/bin:/usr/bin:/usr/ucb:/usr/bsd:/etc:/usr/etc:/usr/sbin";
++char path[] = "PATH=/bin:/usr/bin:/sbin:/usr/sbin";
+
+ #define TIME_LIMIT 60 /* Do not keep listinging forever */
+ #define INPUT_LENGTH 100000 /* Do not keep listinging forever */
+ #define LINE_LENGTH 128 /* Editors can choke on long lines */
+ #define FINGER_PROGRAM "finger" /* Most, if not all, UNIX systems */
+ #define UNPRIV_NAME "nobody" /* Preferred privilege level */
+-#define UNPRIV_UGID 32767 /* Default uid and gid */
++#define UNPRIV_UGID 65534 /* Default uid and gid */
+
+ int finger_pid;
++int allow_severity = SEVERITY;
++int deny_severity = LOG_WARNING;
+
+ void cleanup(sig)
+ int sig;
+diff -Naur tcp_wrappers_7.6/scaffold.c tcp_wrappers_7.6.gimli/scaffold.c
+--- tcp_wrappers_7.6/scaffold.c 1997-03-21 12:27:24.000000000 -0600
++++ tcp_wrappers_7.6.gimli/scaffold.c 2002-01-07 08:50:19.000000000 -0600
+@@ -180,10 +180,12 @@
+
+ /* ARGSUSED */
+
+-void rfc931(request)
+-struct request_info *request;
++void rfc931(rmt_sin, our_sin, dest)
++struct sockaddr_in *rmt_sin;
++struct sockaddr_in *our_sin;
++char *dest;
+ {
+- strcpy(request->user, unknown);
++ strcpy(dest, unknown);
+ }
+
+ /* check_path - examine accessibility */
+diff -Naur tcp_wrappers_7.6/socket.c tcp_wrappers_7.6.gimli/socket.c
+--- tcp_wrappers_7.6/socket.c 1997-03-21 12:27:25.000000000 -0600
++++ tcp_wrappers_7.6.gimli/socket.c 2002-01-07 08:50:19.000000000 -0600
+@@ -76,7 +76,11 @@
+ {
+ static struct sockaddr_in client;
+ static struct sockaddr_in server;
++#if !defined (__GLIBC__)
+ int len;
++#else /* __GLIBC__ */
++ size_t len;
++#endif /* __GLIBC__ */
+ char buf[BUFSIZ];
+ int fd = request->fd;
+
+@@ -224,7 +228,11 @@
+ {
+ char buf[BUFSIZ];
+ struct sockaddr_in sin;
++#if !defined(__GLIBC__)
+ int size = sizeof(sin);
++#else /* __GLIBC__ */
++ size_t size = sizeof(sin);
++#endif /* __GLIBC__ */
+
+ /*
+ * Eat up the not-yet received datagram. Some systems insist on a
+diff -Naur tcp_wrappers_7.6/tcpd.8 tcp_wrappers_7.6.gimli/tcpd.8
+--- tcp_wrappers_7.6/tcpd.8 1996-02-21 09:39:16.000000000 -0600
++++ tcp_wrappers_7.6.gimli/tcpd.8 2002-01-07 08:50:19.000000000 -0600
+@@ -94,7 +94,7 @@
+ .PP
+ The example assumes that the network daemons live in /usr/etc. On some
+ systems, network daemons live in /usr/sbin or in /usr/libexec, or have
+-no `in.\' prefix to their name.
++no `in.' prefix to their name.
+ .SH EXAMPLE 2
+ This example applies when \fItcpd\fR expects that the network daemons
+ are left in their original place.
+@@ -110,26 +110,26 @@
+ becomes:
+ .sp
+ .ti +5
+-finger stream tcp nowait nobody /some/where/tcpd in.fingerd
++finger stream tcp nowait nobody /usr/sbin/tcpd in.fingerd
+ .sp
+ .fi
+ .PP
+ The example assumes that the network daemons live in /usr/etc. On some
+ systems, network daemons live in /usr/sbin or in /usr/libexec, the
+-daemons have no `in.\' prefix to their name, or there is no userid
++daemons have no `in.' prefix to their name, or there is no userid
+ field in the inetd configuration file.
+ .PP
+ Similar changes will be needed for the other services that are to be
+-covered by \fItcpd\fR. Send a `kill -HUP\' to the \fIinetd\fR(8)
++covered by \fItcpd\fR. Send a `kill -HUP' to the \fIinetd\fR(8)
+ process to make the changes effective. AIX users may also have to
+-execute the `inetimp\' command.
++execute the `inetimp' command.
+ .SH EXAMPLE 3
+ In the case of daemons that do not live in a common directory ("secret"
+ or otherwise), edit the \fIinetd\fR configuration file so that it
+ specifies an absolute path name for the process name field. For example:
+ .nf
+ .sp
+- ntalk dgram udp wait root /some/where/tcpd /usr/local/lib/ntalkd
++ ntalk dgram udp wait root /usr/sbin/tcpd /usr/sbin/in.ntalkd
+ .sp
+ .fi
+ .PP
+diff -Naur tcp_wrappers_7.6/tcpd.h tcp_wrappers_7.6.gimli/tcpd.h
+--- tcp_wrappers_7.6/tcpd.h 1996-03-19 09:22:25.000000000 -0600
++++ tcp_wrappers_7.6.gimli/tcpd.h 2002-01-07 08:50:19.000000000 -0600
+@@ -4,6 +4,25 @@
+ * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
+ */
+
++#ifndef _TCPWRAPPERS_TCPD_H
++#define _TCPWRAPPERS_TCPD_H
++
++/* someone else may have defined this */
++#undef __P
++
++/* use prototypes if we have an ANSI C compiler or are using C++ */
++#if defined(__STDC__) || defined(__cplusplus)
++#define __P(args) args
++#else
++#define __P(args) ()
++#endif
++
++/* Need definitions of struct sockaddr_in and FILE. */
++#include <netinet/in.h>
++#include <stdio.h>
++
++__BEGIN_DECLS
++
+ /* Structure to describe one communications endpoint. */
+
+ #define STRING_LENGTH 128 /* hosts, users, processes */
+@@ -25,10 +44,10 @@
+ char pid[10]; /* access via eval_pid(request) */
+ struct host_info client[1]; /* client endpoint info */
+ struct host_info server[1]; /* server endpoint info */
+- void (*sink) (); /* datagram sink function or 0 */
+- void (*hostname) (); /* address to printable hostname */
+- void (*hostaddr) (); /* address to printable address */
+- void (*cleanup) (); /* cleanup function or 0 */
++ void (*sink) __P((int)); /* datagram sink function or 0 */
++ void (*hostname) __P((struct host_info *)); /* address to printable hostname */
++ void (*hostaddr) __P((struct host_info *)); /* address to printable address */
++ void (*cleanup) __P((struct request_info *)); /* cleanup function or 0 */
+ struct netconfig *config; /* netdir handle */
+ };
+
+@@ -61,25 +80,30 @@
+ /* Global functions. */
+
+ #if defined(TLI) || defined(PTX) || defined(TLI_SEQUENT)
+-extern void fromhost(); /* get/validate client host info */
++extern void fromhost __P((struct request_info *)); /* get/validate client host info */
+ #else
+ #define fromhost sock_host /* no TLI support needed */
+ #endif
+
+-extern int hosts_access(); /* access control */
+-extern void shell_cmd(); /* execute shell command */
+-extern char *percent_x(); /* do %<char> expansion */
+-extern void rfc931(); /* client name from RFC 931 daemon */
+-extern void clean_exit(); /* clean up and exit */
+-extern void refuse(); /* clean up and exit */
+-extern char *xgets(); /* fgets() on steroids */
+-extern char *split_at(); /* strchr() and split */
+-extern unsigned long dot_quad_addr(); /* restricted inet_addr() */
++extern void shell_cmd __P((char *)); /* execute shell command */
++extern char *percent_x __P((char *, int, char *, struct request_info *)); /* do %<char> expansion */
++extern void rfc931 __P((struct sockaddr_in *, struct sockaddr_in *, char *)); /* client name from RFC 931 daemon */
++extern void clean_exit __P((struct request_info *)); /* clean up and exit */
++extern void refuse __P((struct request_info *)); /* clean up and exit */
++extern char *xgets __P((char *, int, FILE *)); /* fgets() on steroids */
++extern char *split_at __P((char *, int)); /* strchr() and split */
++extern unsigned long dot_quad_addr __P((char *)); /* restricted inet_addr() */
+
+ /* Global variables. */
+
++#ifdef HAVE_WEAKSYMS
++extern int allow_severity __attribute__ ((weak)); /* for connection logging */
++extern int deny_severity __attribute__ ((weak)); /* for connection logging */
++#else
+ extern int allow_severity; /* for connection logging */
+ extern int deny_severity; /* for connection logging */
++#endif
++
+ extern char *hosts_allow_table; /* for verification mode redirection */
+ extern char *hosts_deny_table; /* for verification mode redirection */
+ extern int hosts_access_verbose; /* for verbose matching mode */
+@@ -92,9 +116,14 @@
+ */
+
+ #ifdef __STDC__
++extern int hosts_access(struct request_info *request);
++extern int hosts_ctl(char *daemon, char *client_name, char *client_addr,
++ char *client_user);
+ extern struct request_info *request_init(struct request_info *,...);
+ extern struct request_info *request_set(struct request_info *,...);
+ #else
++extern int hosts_access();
++extern int hosts_ctl();
+ extern struct request_info *request_init(); /* initialize request */
+ extern struct request_info *request_set(); /* update request structure */
+ #endif
+@@ -117,27 +146,31 @@
+ * host_info structures serve as caches for the lookup results.
+ */
+
+-extern char *eval_user(); /* client user */
+-extern char *eval_hostname(); /* printable hostname */
+-extern char *eval_hostaddr(); /* printable host address */
+-extern char *eval_hostinfo(); /* host name or address */
+-extern char *eval_client(); /* whatever is available */
+-extern char *eval_server(); /* whatever is available */
++extern char *eval_user __P((struct request_info *)); /* client user */
++extern char *eval_hostname __P((struct host_info *)); /* printable hostname */
++extern char *eval_hostaddr __P((struct host_info *)); /* printable host address */
++extern char *eval_hostinfo __P((struct host_info *)); /* host name or address */
++extern char *eval_client __P((struct request_info *)); /* whatever is available */
++extern char *eval_server __P((struct request_info *)); /* whatever is available */
+ #define eval_daemon(r) ((r)->daemon) /* daemon process name */
+ #define eval_pid(r) ((r)->pid) /* process id */
+
+ /* Socket-specific methods, including DNS hostname lookups. */
+
+-extern void sock_host(); /* look up endpoint addresses */
+-extern void sock_hostname(); /* translate address to hostname */
+-extern void sock_hostaddr(); /* address to printable address */
++/* look up endpoint addresses */
++extern void sock_host __P((struct request_info *));
++/* translate address to hostname */
++extern void sock_hostname __P((struct host_info *));
++/* address to printable address */
++extern void sock_hostaddr __P((struct host_info *));
++
+ #define sock_methods(r) \
+ { (r)->hostname = sock_hostname; (r)->hostaddr = sock_hostaddr; }
+
+ /* The System V Transport-Level Interface (TLI) interface. */
+
+ #if defined(TLI) || defined(PTX) || defined(TLI_SEQUENT)
+-extern void tli_host(); /* look up endpoint addresses etc. */
++extern void tli_host __P((struct request_info *)); /* look up endpoint addresses etc. */
+ #endif
+
+ /*
+@@ -178,7 +211,7 @@
+ * behavior.
+ */
+
+-extern void process_options(); /* execute options */
++extern void process_options __P((char *, struct request_info *)); /* execute options */
+ extern int dry_run; /* verification flag */
+
+ /* Bug workarounds. */
+@@ -217,3 +250,7 @@
+ #define strtok my_strtok
+ extern char *my_strtok();
+ #endif
++
++__END_DECLS
++
++#endif /* tcpd.h */
+diff -Naur tcp_wrappers_7.6/tcpdchk.c tcp_wrappers_7.6.gimli/tcpdchk.c
+--- tcp_wrappers_7.6/tcpdchk.c 1997-02-11 19:13:25.000000000 -0600
++++ tcp_wrappers_7.6.gimli/tcpdchk.c 2002-01-07 08:50:19.000000000 -0600
+@@ -350,6 +350,8 @@
+ {
+ if (pat[0] == '@') {
+ tcpd_warn("%s: daemon name begins with \"@\"", pat);
++ } else if (pat[0] == '/') {
++ tcpd_warn("%s: daemon name begins with \"/\"", pat);
+ } else if (pat[0] == '.') {
+ tcpd_warn("%s: daemon name begins with dot", pat);
+ } else if (pat[strlen(pat) - 1] == '.') {
+@@ -382,6 +384,8 @@
+ {
+ if (pat[0] == '@') { /* @netgroup */
+ tcpd_warn("%s: user name begins with \"@\"", pat);
++ } else if (pat[0] == '/') {
++ tcpd_warn("%s: user name begins with \"/\"", pat);
+ } else if (pat[0] == '.') {
+ tcpd_warn("%s: user name begins with dot", pat);
+ } else if (pat[strlen(pat) - 1] == '.') {
+@@ -402,8 +406,13 @@
+ static int check_host(pat)
+ char *pat;
+ {
++ char buf[BUFSIZ];
+ char *mask;
+ int addr_count = 1;
++ FILE *fp;
++ struct tcpd_context saved_context;
++ char *cp;
++ char *wsp = " \t\r\n";
+
+ if (pat[0] == '@') { /* @netgroup */
+ #ifdef NO_NETGRENT
+@@ -422,6 +431,21 @@
+ tcpd_warn("netgroup support disabled");
+ #endif
+ #endif
++ } else if (pat[0] == '/') { /* /path/name */
++ if ((fp = fopen(pat, "r")) != 0) {
++ saved_context = tcpd_context;
++ tcpd_context.file = pat;
++ tcpd_context.line = 0;
++ while (fgets(buf, sizeof(buf), fp)) {
++ tcpd_context.line++;
++ for (cp = strtok(buf, wsp); cp; cp = strtok((char *) 0, wsp))
++ check_host(cp);
++ }
++ tcpd_context = saved_context;
++ fclose(fp);
++ } else if (errno != ENOENT) {
++ tcpd_warn("open %s: %m", pat);
++ }
+ } else if (mask = split_at(pat, '/')) { /* network/netmask */
+ if (dot_quad_addr(pat) == INADDR_NONE
+ || dot_quad_addr(mask) == INADDR_NONE)
+diff -Naur tcp_wrappers_7.6/try-from.8 tcp_wrappers_7.6.gimli/try-from.8
+--- tcp_wrappers_7.6/try-from.8 1969-12-31 18:00:00.000000000 -0600
++++ tcp_wrappers_7.6.gimli/try-from.8 2002-01-07 08:50:19.000000000 -0600
+@@ -0,0 +1,28 @@
++.TH TRY-FROM 8 "21th June 1997" Linux "Linux Programmer's Manual"
++.SH NAME
++try-from \- test program for the tcp_wrapper
++.SH SYNOPSIS
++.B try-from
++.SH DESCRIPTION
++The
++.B try-from
++command can be called via a remote shell command to find out
++if the hostname and address are properly recognized
++by the
++.B tcp_wrapper
++library, if username lookup works, and (SysV only) if the TLI
++on top of IP heuristics work. Diagnostics are reported through
++.BR syslog (3)
++and redirected to stderr.
++
++Example:
++
++rsh host /some/where/try-from
++
++.SH SEE ALSO
++.BR hosts_access (5),
++.BR hosts_options (5),
++.BR tcpd (8)
++.SH AUTHOR
++Wietse Venema, Eindhoven University of Technology, The Netherlands.
++
+diff -Naur tcp_wrappers_7.6/weak_symbols.c tcp_wrappers_7.6.gimli/weak_symbols.c
+--- tcp_wrappers_7.6/weak_symbols.c 1969-12-31 18:00:00.000000000 -0600
++++ tcp_wrappers_7.6.gimli/weak_symbols.c 2002-01-07 08:50:19.000000000 -0600
+@@ -0,0 +1,11 @@
++ /*
++ * @(#) weak_symbols.h 1.5 99/12/29 23:50
++ *
++ * Author: Anthony Towns <ajt@debian.org>
++ */
++
++#ifdef HAVE_WEAKSYMS
++#include <syslog.h>
++int deny_severity = LOG_WARNING;
++int allow_severity = SEVERITY;
++#endif
+diff -Naur tcp_wrappers_7.6/workarounds.c tcp_wrappers_7.6.gimli/workarounds.c
+--- tcp_wrappers_7.6/workarounds.c 1996-03-19 09:22:26.000000000 -0600
++++ tcp_wrappers_7.6.gimli/workarounds.c 2002-01-07 08:50:19.000000000 -0600
+@@ -163,7 +163,11 @@
+ int fix_getpeername(sock, sa, len)
+ int sock;
+ struct sockaddr *sa;
++#if !defined(__GLIBC__)
+ int *len;
++#else /* __GLIBC__ */
++size_t *len;
++#endif /* __GLIBC__ */
+ {
+ int ret;
+ struct sockaddr_in *sin = (struct sockaddr_in *) sa;
--- /dev/null
+diff -Naur systemd-208.org/src/udev/mtd_probe/mtd_probe.h systemd-208/src/udev/mtd_probe/mtd_probe.h
+--- systemd-208.org/src/udev/mtd_probe/mtd_probe.h 2013-08-13 22:02:47.000000000 +0200
++++ systemd-208/src/udev/mtd_probe/mtd_probe.h 2017-02-07 18:08:33.492985563 +0100
+@@ -18,6 +18,7 @@
+ */
+
+ #include <mtd/mtd-user.h>
++#include <stdint.h>
+
+ /* Full oob structure as written on the flash */
+ struct sm_oob {
--- /dev/null
+diff -Naur systemd-208.org/src/libudev/libudev-util.c systemd-208/src/libudev/libudev-util.c
+--- systemd-208.org/src/libudev/libudev-util.c 2013-09-23 21:31:55.000000000 +0200
++++ systemd-208/src/libudev/libudev-util.c 2013-11-19 23:18:10.326350131 +0100
+@@ -481,7 +481,7 @@
+ if (fd < 0)
+ return -errno;
+
+- len = snprintf(text, sizeof(text), "<30>systemd-udevd[%u]: ", getpid());
++ len = snprintf(text, sizeof(text), "udevd[%u]: ", getpid());
+
+ va_start(ap, fmt);
+ len += vsnprintf(text + len, sizeof(text) - len, fmt, ap);