[Midnightbsd-cvs] src [8885] trunk/sys/dev/ata: allow for odd aligned buffers as passed in by smartd of smartmontools.

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Mon Sep 26 18:25:18 EDT 2016


Revision: 8885
          http://svnweb.midnightbsd.org/src/?rev=8885
Author:   laffer1
Date:     2016-09-26 18:25:18 -0400 (Mon, 26 Sep 2016)
Log Message:
-----------
allow for odd aligned buffers as passed in by smartd of smartmontools.

Modified Paths:
--------------
    trunk/sys/dev/ata/ata-all.h
    trunk/sys/dev/ata/ata-lowlevel.c

Modified: trunk/sys/dev/ata/ata-all.h
===================================================================
--- trunk/sys/dev/ata/ata-all.h	2016-09-26 22:24:17 UTC (rev 8884)
+++ trunk/sys/dev/ata/ata-all.h	2016-09-26 22:25:18 UTC (rev 8885)
@@ -698,6 +698,8 @@
 
 #define ATA_INW(res, offset) \
 	bus_read_2((res), (offset))
+#define ATA_INW_STRM(res, offset) \
+	bus_read_stream_2((res), (offset))
 #define ATA_INL(res, offset) \
 	bus_read_4((res), (offset))
 #define ATA_INSW(res, offset, addr, count) \
@@ -712,6 +714,8 @@
 	bus_write_1((res), (offset), (value))
 #define ATA_OUTW(res, offset, value) \
 	bus_write_2((res), (offset), (value))
+#define ATA_OUTW_STRM(res, offset, value) \
+	bus_write_stream_2((res), (offset), (value))
 #define ATA_OUTL(res, offset, value) \
 	bus_write_4((res), (offset), (value))
 #define ATA_OUTSW(res, offset, addr, count) \
@@ -729,6 +733,9 @@
 #define ATA_IDX_INW(ch, idx) \
 	ATA_INW(ch->r_io[idx].res, ch->r_io[idx].offset)
 
+#define ATA_IDX_INW_STRM(ch, idx) \
+	ATA_INW_STRM(ch->r_io[idx].res, ch->r_io[idx].offset)
+
 #define ATA_IDX_INL(ch, idx) \
 	ATA_INL(ch->r_io[idx].res, ch->r_io[idx].offset)
 
@@ -750,6 +757,9 @@
 #define ATA_IDX_OUTW(ch, idx, value) \
 	ATA_OUTW(ch->r_io[idx].res, ch->r_io[idx].offset, value)
 
+#define ATA_IDX_OUTW_STRM(ch, idx, value) \
+	ATA_OUTW_STRM(ch->r_io[idx].res, ch->r_io[idx].offset, value)
+
 #define ATA_IDX_OUTL(ch, idx, value) \
 	ATA_OUTL(ch->r_io[idx].res, ch->r_io[idx].offset, value)
 

Modified: trunk/sys/dev/ata/ata-lowlevel.c
===================================================================
--- trunk/sys/dev/ata/ata-lowlevel.c	2016-09-26 22:24:17 UTC (rev 8884)
+++ trunk/sys/dev/ata/ata-lowlevel.c	2016-09-26 22:25:18 UTC (rev 8885)
@@ -847,14 +847,28 @@
     uint8_t *addr;
     int size = min(request->transfersize, length);
     int resid;
-    uint8_t buf[2];
+    uint8_t buf[2] __aligned(sizeof(int16_t));
+#ifndef __NO_STRICT_ALIGNMENT
+    int i;
+#endif
 
     addr = (uint8_t *)request->data + request->donecount;
-    if (ch->flags & ATA_USE_16BIT || (size % sizeof(int32_t)) ||
-	((uintptr_t)addr % sizeof(int32_t))) {
-	ATA_IDX_INSW_STRM(ch, ATA_DATA, (void*)addr, size / sizeof(int16_t));
+    if (__predict_false(ch->flags & ATA_USE_16BIT ||
+      (size % sizeof(int32_t)) || ((uintptr_t)addr % sizeof(int32_t)))) {
+#ifndef __NO_STRICT_ALIGNMENT
+	if (__predict_false((uintptr_t)addr % sizeof(int16_t))) {
+	    for (i = 0, resid = size & ~1; resid > 0; resid -=
+	      sizeof(int16_t)) {
+		*(uint16_t *)&buf = ATA_IDX_INW_STRM(ch, ATA_DATA);
+	        addr[i++] = buf[0];
+	        addr[i++] = buf[1];
+	    }
+	} else
+#endif
+	    ATA_IDX_INSW_STRM(ch, ATA_DATA, (void*)addr, size /
+	      sizeof(int16_t));
 	if (size & 1) {
-	    ATA_IDX_INSW_STRM(ch, ATA_DATA, (void*)buf, 1);
+	    *(uint16_t *)&buf = ATA_IDX_INW_STRM(ch, ATA_DATA);
 	    (addr + (size & ~1))[0] = buf[0];
 	}
     } else
@@ -876,15 +890,30 @@
     uint8_t *addr;
     int size = min(request->transfersize, length);
     int resid;
-    uint8_t buf[2];
+    uint8_t buf[2] __aligned(sizeof(int16_t));
+#ifndef __NO_STRICT_ALIGNMENT
+    int i;
+#endif
 
+    size = min(request->transfersize, length);
     addr = (uint8_t *)request->data + request->donecount;
-    if (ch->flags & ATA_USE_16BIT || (size % sizeof(int32_t)) ||
-	((uintptr_t)addr % sizeof(int32_t))) {
-	ATA_IDX_OUTSW_STRM(ch, ATA_DATA, (void*)addr, size / sizeof(int16_t));
+    if (__predict_false(ch->flags & ATA_USE_16BIT ||
+      (size % sizeof(int32_t)) || ((uintptr_t)addr % sizeof(int32_t)))) {
+#ifndef __NO_STRICT_ALIGNMENT
+	if (__predict_false((uintptr_t)addr % sizeof(int16_t))) {
+	    for (i = 0, resid = size & ~1; resid > 0; resid -=
+	      sizeof(int16_t)) {
+	        buf[0] = addr[i++];
+	        buf[1] = addr[i++];
+		ATA_IDX_OUTW_STRM(ch, ATA_DATA, *(uint16_t *)&buf);
+	    }
+	} else
+#endif
+	    ATA_IDX_OUTSW_STRM(ch, ATA_DATA, (void*)addr, size /
+	      sizeof(int16_t));
 	if (size & 1) {
 	    buf[0] = (addr + (size & ~1))[0];
-	    ATA_IDX_OUTSW_STRM(ch, ATA_DATA, (void*)buf, 1);
+	    ATA_IDX_OUTW_STRM(ch, ATA_DATA, *(uint16_t *)&buf);
 	}
     } else
 	ATA_IDX_OUTSL_STRM(ch, ATA_DATA, (void*)addr, size / sizeof(int32_t));



More information about the Midnightbsd-cvs mailing list